如何使用 C++ 模块:带有模板的私有片段?
How to use C++ module :private fragment with templates?
我正在试验 C++20 以更好地理解它们在实践中的工作原理。我了解到 module :private
片段可用于将接口与实现分开,同时将两者保存在同一个文件中。这似乎适用于标准函数,但不适用于模板函数。
我有以下文件:
// File "main.cpp"
#include <iostream>
import mymodule;
int main()
{
std::cout << "greeting(): " << mymodule::greetings() << std::endl;
int x = 1;
int y = 2;
std::cout << "add(x, y): " << mymodule::add(x, y) << std::endl;
}
// File "mymodule.ixx"
module;
#include <string>
// declare interface
export module mymodule;
export namespace mymodule {
template<typename T>
T add(T x, T y);
std::string greetings();
}
// implement interface
module :private;
std::string mymodule::greetings() {
return "hello";
}
template<typename T>
T mymodule::add(T x, T y) {
return x + y;
}
并得到编译器警告和链接器错误(使用 Visual Studio 2022,MSVC):
Rebuild started...
1>------ Rebuild All started: Project: PlayingWithModules, Configuration: Debug x64 ------
1>Scanning sources for module dependencies...
1>mymodule.ixx
1>Compiling...
1>mymodule.ixx
1>C:\Users\Sam\Development\Cpp\Sandbox\PlayingWithModules\mymodule.ixx(29,13): warning C5226: 'mymodule::add': exported template defined in private module fragment has no reachable instantiation
1>main.cpp
1>main.obj : error LNK2019: unresolved external symbol "int __cdecl mymodule::add<int>(int,int)" (??$add@H@mymodule@@YAHHH@Z::<!mymodule>) referenced in function main
1>C:\Users\Sam\Development\Cpp\Sandbox\x64\Debug\PlayingWithModules.exe : fatal error LNK1120: 1 unresolved externals
1>Done building project "PlayingWithModules.vcxproj" -- FAILED.
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
我的理解是mymodule::greetings()
是可以的,但是mymodule::add(x, y)
不是因为编译器看不到函数调用mymodule::<int, int>(x, y)
,导致没有函数<int, int>
正在生成。
如果我改为将模板函数实现为接口的一部分:
module;
#include <string>
// declare interface
export module mymodule;
export namespace mymodule {
template<typename T>
T add(T x, T y) {
return x + y;
}
std::string greetings();
}
// implement interface
module :private;
std::string mymodule::greetings() {
return "hello";
}
然后一切都按预期编译和工作。
是否可以将 module :private
与函数模板一起使用,如果可以,如何使用?或者模板函数是否应该始终作为接口的一部分来实现?我无法在网上找到有关模块上下文中模板使用的详细信息,也找不到对我收到的编译器警告的引用。
模块不会改变 C++ 的性质,只会改变你访问不同组件的方式。
C++ 的本质是,为了让翻译单元使用模板,该翻译单元必须能够访问该模板的 定义 。模块不会改变这一点。
私有模块片段特别包含不模块接口的部分。这就是它们的全部意义所在:能够将不属于接口的内容粘贴到模块文件中。
因此,私有模块片段只能包含您要放入传统 .cpp 文件中的内容。事实上,这就是它们存在的原因:这样(对于短模块)您可以将所有常用的 .cpp 内容放在一个文件中,而不会影响模块生成的内容。
我正在试验 C++20 以更好地理解它们在实践中的工作原理。我了解到 module :private
片段可用于将接口与实现分开,同时将两者保存在同一个文件中。这似乎适用于标准函数,但不适用于模板函数。
我有以下文件:
// File "main.cpp"
#include <iostream>
import mymodule;
int main()
{
std::cout << "greeting(): " << mymodule::greetings() << std::endl;
int x = 1;
int y = 2;
std::cout << "add(x, y): " << mymodule::add(x, y) << std::endl;
}
// File "mymodule.ixx"
module;
#include <string>
// declare interface
export module mymodule;
export namespace mymodule {
template<typename T>
T add(T x, T y);
std::string greetings();
}
// implement interface
module :private;
std::string mymodule::greetings() {
return "hello";
}
template<typename T>
T mymodule::add(T x, T y) {
return x + y;
}
并得到编译器警告和链接器错误(使用 Visual Studio 2022,MSVC):
Rebuild started...
1>------ Rebuild All started: Project: PlayingWithModules, Configuration: Debug x64 ------
1>Scanning sources for module dependencies...
1>mymodule.ixx
1>Compiling...
1>mymodule.ixx
1>C:\Users\Sam\Development\Cpp\Sandbox\PlayingWithModules\mymodule.ixx(29,13): warning C5226: 'mymodule::add': exported template defined in private module fragment has no reachable instantiation
1>main.cpp
1>main.obj : error LNK2019: unresolved external symbol "int __cdecl mymodule::add<int>(int,int)" (??$add@H@mymodule@@YAHHH@Z::<!mymodule>) referenced in function main
1>C:\Users\Sam\Development\Cpp\Sandbox\x64\Debug\PlayingWithModules.exe : fatal error LNK1120: 1 unresolved externals
1>Done building project "PlayingWithModules.vcxproj" -- FAILED.
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
我的理解是mymodule::greetings()
是可以的,但是mymodule::add(x, y)
不是因为编译器看不到函数调用mymodule::<int, int>(x, y)
,导致没有函数<int, int>
正在生成。
如果我改为将模板函数实现为接口的一部分:
module;
#include <string>
// declare interface
export module mymodule;
export namespace mymodule {
template<typename T>
T add(T x, T y) {
return x + y;
}
std::string greetings();
}
// implement interface
module :private;
std::string mymodule::greetings() {
return "hello";
}
然后一切都按预期编译和工作。
是否可以将 module :private
与函数模板一起使用,如果可以,如何使用?或者模板函数是否应该始终作为接口的一部分来实现?我无法在网上找到有关模块上下文中模板使用的详细信息,也找不到对我收到的编译器警告的引用。
模块不会改变 C++ 的性质,只会改变你访问不同组件的方式。
C++ 的本质是,为了让翻译单元使用模板,该翻译单元必须能够访问该模板的 定义 。模块不会改变这一点。
私有模块片段特别包含不模块接口的部分。这就是它们的全部意义所在:能够将不属于接口的内容粘贴到模块文件中。
因此,私有模块片段只能包含您要放入传统 .cpp 文件中的内容。事实上,这就是它们存在的原因:这样(对于短模块)您可以将所有常用的 .cpp 内容放在一个文件中,而不会影响模块生成的内容。