首页 > 解决方案 > C ++如何从模块中正确打印模板类型的值

问题描述

我在模块中有一个向量类:

// other_library.cpp
module;
#include <iostream>

export module mylibrary.other;

export template<class T> class Vector
{
private:
    T x, y;

public:
    Vector(T _x, T _y) : x(_x), y(_y) {}

    void Write()
    {
        std::cout << "Vector{" << x << ", " << y << "}\n";
    }
};

在 main 里面,我创建了一个向量并打印它的内容:

// main.cpp
import mylibrary.other;

int main()
{
    Vector<int> vec(1, 2);
    vec.Write();

    return 0;
}

但是,我在终端上得到了意外的打印: Vector{10x55a62f2f100c20x55a62f2f100f

这些是使用的构建命令:

g++-11 -std=c++20 -fmodules-ts -c other_library.cpp
g++-11 -std=c++20 -fmodules-ts -c main.cpp
g++-11 -std=c++20 -fmodules-ts *.o -o app
./app

自然,如果我将矢量类移动到主文件,打印将按预期工作。我知道模块支持仍然是实验性的。但我希望像这样简单的事情能够正常工作。但也许我做错了什么?

编辑:

一种破坏技巧是在导入模块之前手动将 iostream 包含在主文件的顶部,如下所示:

// main.cpp
#include <iostream>
import mylibrary.other;

int main()
{
    Vector<int> vec(1, 2);
    vec.Write();

    return 0;
}

这将正确打印 Vector 的内容。但为什么这是必要的?将东西放入模块中的目的是避免包含标题的麻烦。

因此,我的问题现在有两个方面。

标签: c++templatesmodulec++20

解决方案


因此,模块似乎仍然存在一些挑战。示例:我不能在成员函数std::endl内部使用。Vector.Write

一种解决方案是预编译iostream标准头文件,可以这样完成:

g++-11 -std=c++20 -fmodules-ts -xc++-system-header iostream

预编译的模块将存储在 gcm.cached/ 目录中,并且将是连续 gcc 命令的隐式搜索路径。

现在,我可以完全避免包含标准头文件,所以库文件现在看起来像这样:

// other_library.cpp
export module mylibrary.other;
import <iostream>;

export template<class T> class Vector
{
private:
    T x, y;

public:
    Vector(T _x, T _y) : x(_x), y(_y) {}

    void Write()
    {
        std::cout << "Vector{" << x << ", " << y << "}"
                  << std::endl;
    }
};

而且我不需要在主文件中做任何进一步的事情 - 只需导入我的库模块就足够了。

非常感谢 Šimon Tóth 在他的关于模块的文章中写到这一点。


推荐阅读