Home > Net >  Exporting template function requiring std concepts
Exporting template function requiring std concepts

Time:12-21

IDE : MSVS 2022, /std:c latest, /experimental:module, x86 ;

Goal : to export T add(T,T) that requires std::integral<T> ;

This compiles (test.ixx) :

export module test;

template < typename T >
concept addable = requires ( T t1, T t2 ) {
    t1   t2 ;
};

export template < typename T >
requires addable<T>
T add ( T t1, T t2 ) { return t1   t2; }

This does not (test.ixx) :

export module test;

#include <concepts>

export template < typename T >
requires std::integral<T>
T add ( T t1, T t2 ) { return t1   t2; }

The above code causes 2 errors LNK2019, details below ;

Tried to

  1. #include <concepts> in a separate implementation file - failed ;
  2. import std.core;, which seems to not yet be supported - failed ;

Usage sample (main.cpp) :

import test;
#include <iostream>

int main ()
{
    using namespace std;
   
    int    i = add(22,20);              // = 42
    double d = add(0.5,0.77);           // = 1.27

    cout << i << ", " << d << endl ;    // "42, 1.27"

    return 0;
}

Any ideas ?

Linker error details :

LNK2019 : unresolved external symbol __imp__ldiv::<!test> referenced in function "struct test::_ldiv_t __cdecl div(long,long)" (?div@@YA?AU_ldiv_t@test@@JJ@Z::<!test>)
LNK2019 : unresolved external symbol __imp__lldiv::<!test> referenced in function "struct test::_lldiv_t __cdecl div(__int64,__int64)" (?div@@YA?AU_lldiv_t@test@@_J0@Z::<!test>)

CodePudding user response:

The thing is, you shouldn't use #include after the module declaration export module xxx.

The introduction of modules does not change what #include means (well, in most cases), #include still means "copy-paste this file here". Your #include-ing of <concepts> pasted all its content and its transitive includes into your module, and your module now "owns" these definitions (they have module linkage). The compiler mangles names belong to modules differently, and that's what causes the linker errors.

You should instead use the global module fragment for #include-ing things:

module;
#include <concepts>
export module test;
// contents

Or use "header units" (provided your compiler supports them) instead:

export module test;
import <concepts>;
// contents
  • Related