Before re-factoring my project for use with Modules I wrote a test project, ExImMod
, to see if I could separate out declarations and definitions as advertised in the Modules documentation. For my project, I need to keep the declarations and definitions in separate translation units (TU), which is also possible according to the Modules documentation. I do not want to use Module Partitions.
Unfortunately, my test ExImMod
project indicates that they cannot be fully separated, at least for the Visual Studio 2022 (std:c++latest) compiler (VS22).
Here is my main test program:
// ExImModMain.cpp
import FuncEnumNum;
import AStruct;
int main()
{
A a;
a.MemberFunc();
}
A's member function, MemberFunc()
, is declared here:
// AStruct.ixx
// module; // global fragment moved to AMemberFunc.cppm (Nicol Bolas)
// #include <iostream>
export module AStruct; // primary interface module
export import FuncEnumNum; // export/imports functionalities declared in FuncEnumNum.ixx and defined in MyFunc.cppm
#include "AMemberFunc.hxx" // include header declaration
which includes the `AMemberFunc.hxx' declaration and definition:
// AMemberFunc.hxx
export struct A
{
int MemberFunc()
{
if( num == 35 ) // OK: 'num' is defined in primary interface module 'FuncEnumNum.ixx'
{
std::cout << "num is 35\n"; // OK: 'cout' is included in global fragment
}
num = MyFunc(); // OK: 'MyFunc' is declared in primary interface module and defined in 'MyFunc.cppm' module unit
if( hwColors == HwColors::YELLOW ) // OK: 'hwColors' is declared in primary interface module
{
std::cout << "hwColor is YELLOW\n";
}
return 44;
}
};
Here is the definition that uses the function, enum and int functionalities:
// AMemberFunc.hxx
export struct A
{
int MemberFunc()
{
if( num == 35 ) // OK: 'num' is defined in primary interface module 'FuncEnumNum.ixx'
{
std::cout << "num is 35\n"; // OK: 'cout' is included in global fragment
}
num = MyFunc(); // OK: 'MyFunc' is declared in primary interface module and defined in 'MyFunc.cppm' module unit
if( hwColors == HwColors::YELLOW ) // OK: 'hwColors' is declared in primary interface module
{
std::cout << "hwColor is YELLOW\n";
}
return 44;
}
};
This TU declares these functionalities:
// FuncEnumNum.ixx
export module FuncEnumNum; // module unit
export int num { 35 }; // OK: export and direct init of 'num'
export int MyFunc(); // OK: declaration of 'MyFunc'
export enum class HwColors // OK: declaration of enum
{
YELLOW,
BROWN,
BLUE
};
export HwColors hwColors { HwColors::YELLOW }; // OK: direct init of enum
with MyFunc()
defined in a separate TU:
// MyFunc.cppm
module FuncEnumNum; // module implementation unit
int MyFunc() // OK: definition of function in module unit
{
return 33;
}
This means MemberFunc()
definition is in the primary interface, which works fine. But this does not do what I need for my project. To test that, I remove the definition of MemberFunc()
;
// AMemberFunc.hxx
export struct A
{
int MemberFunc(); // declares 'MemberFunc'
};
and put it in a separate TU:
// AMemberFunc.cppm
module;
#include <iostream>
module MemberFunc; // module unit
import AStruct; // (see Nicol Bolas answer)
int MemberFunc()
{
if( num == 35 ) // OK
{
std::cout << "num is 35\n"; // OK
}
num = MyFunc(); // OK
if( hwColors == HwColors::YELLOW ) OK
{
std::cout << "hwColor is YELLOW\n";
}
return 44;
}
But VS22 cannot find the declarations for 'num', 'MyFunc' and 'HwColor' when the implementation is in the separate module.
My understanding of Modules is, if I import an interface, like I do in import FuncEnumNum;
, then all of its declarations and definitions should be visible in subsequent modules. This does not seem to be the case.
Any ideas as to why this doesn't work here?