【问题标题】:How to use C++ module :private fragment with templates?如何使用 C++ 模块:带有模板的私有片段?
【发布时间】:2022-01-22 17:00:16
【问题描述】:

我正在尝试使用 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::&lt;int, int&gt;(x, y),导致没有生成函数&lt;int, int&gt;


如果我将模板函数作为接口的一部分实现:

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++ templates c++20 constexpr c++-modules


    【解决方案1】:

    模块不会改变 C++ 的性质,只会改变您访问不同组件的方式。

    为了让翻译单元使用模板,该翻译单元必须有权访问该模板的定义,这是 C++ 本质的一部分。模块不会改变这一点。

    私有模块片段具体包含不属于模块接口的部分内容。这就是它们的全部意义:能够将不属于接口的内容粘贴到模块文件中。

    因此,私有模块片段只能包含您将放入传统 .cpp 文件的内容。事实上,这就是它们存在的原因:因此(对于短模块)您可以将所有常用的 .cpp 内容放在一个文件中,而不会影响模块生成的内容。

    【讨论】:

    • 谢谢@Nicol Bolas,这正是我需要的信息!
    • 以防万一有人发现此页面正在寻找 constexpr:private fragment 一起使用:推理与模板相同,constexpr 表达式必须在编译时对编译器完全可用翻译单元,因此必须定义为界面的一部分。
    猜你喜欢
    • 2017-02-19
    • 1970-01-01
    • 2018-12-21
    • 1970-01-01
    • 1970-01-01
    • 2016-04-18
    • 2014-11-27
    • 2021-07-20
    • 1970-01-01
    相关资源
    最近更新 更多