标签: c++-modules

在 C++20 中混合模块和头文件是否可能/可接受?

我实际上是在尝试通过编写自己的小模块来理解 C++20 模块系统。假设我想提供一个函数来删除字符串开头和结尾的所有空格(一个trim函数)。下面的代码工作没有问题

module;

export module String;

import std.core;

export std::string delete_all_spaces(std::string const & string)
{
    std::string copy { string };

    auto first_non_space { std::find_if_not(std::begin(copy), std::end(copy), isspace) };
    copy.erase(std::begin(copy), first_non_space);

    std::reverse(std::begin(copy), std::end(copy));
    first_non_space = std::find_if_not(std::begin(copy), std::end(copy), isspace);
    copy.erase(std::begin(copy), first_non_space);
    std::reverse(std::begin(copy), std::end(copy));

    return copy;
}
Run Code Online (Sandbox Code Playgroud)
import std.core;
import String;

int main()
{
    std::cout << delete_all_spaces("  Hello World!    \n");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是如果我只想使用特定的头文件而不是std.core在我的模块中呢?如果这样做,将 替换为import std.core以下代码,我会在 Visual Studio 2019 上收到错误消息。

module;

#include <algorithm> …
Run Code Online (Sandbox Code Playgroud)

c++ c++20 c++-modules

6
推荐指数
1
解决办法
423
查看次数

使用旧头文件作为 c++20 模块

我正在将旧代码转换为可作为 c++ 模块导入的代码。问题是我希望它仍然可以工作并且可以轻松维护为旧的标头/源版本。我该怎么做(如果可能)。

是否可以创建一个导出标题内容的模块?(任何其他可以让您维护旧的 .cpp/.h 文件和模块文件的解决方案也被接受)

玩具示例:

// In vector.h
template <typename T>
struct Vector {
    T x, y;
}

// In .cppm
export module vector;
// #include "vector.h"
// Export struct/class Vector from header
Run Code Online (Sandbox Code Playgroud)

我尝试过的只是export Vector不同的版本,有和没有模板等。

额外问题:您可以为 std lib 执行此操作吗?(例如 iostream 或字符串)

c++ clang++ c++-modules

6
推荐指数
1
解决办法
1172
查看次数

有没有办法用 gcc 查询直接模块依赖关系?

给定一个模块

// a-m.cc
export module A;

import B;
import C;

import "D.h";

...
Run Code Online (Sandbox Code Playgroud)

有没有一种调用 gcc 的方法(类似于 -M 对标头所做的操作)来列出对其他模块和导入标头(即 B、C 和“Dh”)的直接依赖项?

c++ gcc c++20 c++-modules

6
推荐指数
1
解决办法
1192
查看次数

C++ 模块是否会使未命名的命名空间变得多余?

C++20 引入了模块。任何未在模块中导出的符号都具有模块内部链接。虽然未命名命名空间提供了一种机制,可以使未命名命名空间内的定义具有文件内部链接。这是否意味着当模块在 C++ 社区中成为普遍做法时,未命名的命名空间将变得毫无用处?

c++ namespaces unnamed-namespace c++-modules

6
推荐指数
1
解决办法
428
查看次数

如何使用 g++ 在 c++ 20 中使用模块?

我阅读了此链接https://gcc.gnu.org/wiki/cxx-modules并尝试从该网站复制以下示例。我已经知道这个编译器部分支持模块系统。(注:我用的是windows)

// hello.cc
module;
#include <iostream>
#include <string_view>
export module hello;
export void greeter(std::string_view const &name) {
  std::cout << "Hello " << name << "!\n";
}
Run Code Online (Sandbox Code Playgroud)
// main.cc
import hello;
int main() {
  greeter("world");
  return 0;
}
// Should print "Hello world!" 
Run Code Online (Sandbox Code Playgroud)

我目前有GCC 11.0.1快照,并尝试使用以下参数编译这些文件: g++ -std=gnu++2b -Wall -fmodules-ts hello.cc main.cc编译器给了我这些错误:

hello.cc:6:8: internal compiler error: in get_cxx_dialect_name, at cp/name-lookup.c:7027
    6 | export module hello;
      |        ^~~~~~
libbacktrace could not find executable to open
Please submit …
Run Code Online (Sandbox Code Playgroud)

c++ g++ c++20 c++-modules

6
推荐指数
1
解决办法
6381
查看次数

如何定义导出常量?

我一直在尝试新的模块功能,但无法导出全局常量。导出似乎编译得很好,但导入时编译器抱怨未声明常量。我的代码:

\n

测试.cpp

\n
export module test;\n\nexport struct my_type { int x, y; };\nexport constexpr int my_constant = 42;\nexport int my_function() { return my_constant; }\n
Run Code Online (Sandbox Code Playgroud)\n

主程序

\n
import test;\n\nint main() {\n    my_type t{1, 2};\n    int i = my_function();\n    int j = my_constant; // <- error here\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我究竟做错了什么?我在 Linux 上使用 g++ 11.1.0:g++-11 -std=c++20 -fmodules-ts test.cpp main.cpp -o main

\n

错误信息是:error: \xe2\x80\x98my_constant\xe2\x80\x99 was not declared in this scope

\n

c++ constants c++20 c++-modules

6
推荐指数
1
解决办法
1733
查看次数

为什么 GCC-11 在包含这组特定的标准库时会出现段错误?

双重编辑:仅在使用 libstdc++ 时,同一代码上的可能错误和 Clang 段错误导致 GCC 段错误。起初我不知道这是因为编译器段错误并不是特别有用,但是使用标志 -stdlib=libc++,您可以使用 clang 来很好地编译此代码。使用 libstdc++ 时的 Clang 段错误是一个单独的问题,这个问题特别关注 GCC。

可以在相关的错误报告 #101184 中找到进一步简化的 GCC 示例。如果您对解决方案感兴趣,我建议您关注错误报告。


在下面的代码墙中,有几个小的 c++20 模块在使用包含的命令构建时会导致GCC-11编译器段错误。

我尝试在下面的文本中解释这个问题,但这个问题有点挑剔,我发现理解它的最好方法是稍微玩一下。

其中两个模块“filler1”和“filler2”不导出任何内容,仅在导出模块指令之前包含几个标准库。因为实际上没有从这两者中导出任何内容,所以我预计它不会对程序行为产生任何影响,但出于某种原因,如果两者都包含在内,则会出现 GCC 段错误。如果以任何顺序删除任何一个,程序都可以正常编译。此外,这些填充模块中包含的标准库是特殊的,如果删除“功能”或“内存”,即使它们没有在整个程序中的任何地方使用,它也可以很好地编译。

还有 testmod1 模块,它只包含“向量”。但与填充模块不同,要发生段错误,必须在导出模块指令之后定义任意类型的向量,可以导出也可以不导出。

最后一个可能也是最奇怪的部分是 testmodp 模块。除了所有先前存在的微粒之外,模板结构:template<typename...Ts>与成员向量:std::vectorstd::variant<Ts...>必须定义,然后由 test_impl 模块实例化. 如果我从结构中删除模板并将成员更改为:“ std::vector<std::variant<int, float>> ”它也可以正常工作,即使它与模板类型实例化的类型相同反而。谁能帮我理解这里发生了什么?

注意:因为这个错误非常特别,一个 5 文件示例是我可以在不改变行为的情况下将它提取到的最小文件,我也不允许包含链接,所以如果你想测试它,复制所有带有相应名称的内容。如果这里有什么不对的地方,请随时在评论中联系(:

谢谢阅读!

文件“filler1.cc”

module;
#include <memory>

export module filler1;
Run Code Online (Sandbox Code Playgroud)

文件“filler2.cc”

module;
#include <memory>
#include <functional>

export module filler2;
Run Code Online (Sandbox Code Playgroud)

文件“testmodp.cc”

module;
#include <functional>
#include <vector>
#include <variant>

export module …
Run Code Online (Sandbox Code Playgroud)

c++ gcc c++20 c++-modules

6
推荐指数
0
解决办法
245
查看次数

缺少 Apple Clang 13 C++20 模块支持

根据官方文档,Clang 13 通过使用-fmodules命令行参数支持 C++20 模块。

我什至无法在基于 Intel 或 M1 的 Mac 上使用 Clang 13 (macOS Monterey) 编译基本模块。

假设文件的文本内容如下module.cpp

export module a;

export int f(int a, int b) {
    return a + b;
}
Run Code Online (Sandbox Code Playgroud)

运行以下命令:

$ clang++ --version
Apple clang version 13.0.0 (clang-1300.0.29.3)
Target: x86_64-apple-darwin21.1.0

$ clang++ -std=c++20 -stdlib=libc++ -fmodules -fbuiltin-module-map -c module.cpp 
module.cpp:1:8: error: expected template
export module a;
       ^
module.cpp:1:8: error: unknown type name 'module'
module.cpp:3:8: error: expected template
export int f(int a, …
Run Code Online (Sandbox Code Playgroud)

clang++ c++20 c++-modules apple-m1 macos-monterey

6
推荐指数
1
解决办法
8038
查看次数

在 C++20 上有条件导入模块

有没有办法在没有预处理器指令的情况下有条件地导入模块C++20

伪代码:

if WINDOWS:
    import my_module;
else:
    import other_module;
Run Code Online (Sandbox Code Playgroud)

如果没有办法,使用预处理器最干净的方法是什么?

c++ c++20 c++-modules

6
推荐指数
1
解决办法
674
查看次数

非导出声明和私有模块片段中的声明有什么区别?

cppreference.com 关于模块的内容上,它说export

\n
\n

模块接口单元可以导出声明和定义,这些声明和定义可以由其他翻译单元导入。\n[\xe2\x80\xaf\xe2\x80\xa6\xe2\x80\xaf] \n模块接口中导出的
所有声明和定义给定命名模块的单元将在使用导入声明的翻译单元中可用。

\n
\n

据此猜测,我拥有export该模块的用户想要或需要使用它的一切。所有未export编辑的内容都是模块的实现细节,与importers\xe2\x80\x99 无关。

\n

它还告诉我

\n
\n

私有模块片段[ \xe2\x80\xaf\xe2\x80\xa6\xe2\x80\xaf] 允许将模块表示为单个翻译单元,而不使导入器可以访问模块的所有内容。

\n
\n

将某些内容放入私有模块片段中与不放入其中有什么区别exporting 有什么区别?\n我猜\xe2\x80\x99s 与使用导入声明\xe2\x80 的翻译单元中的\xe2\x80\x9cavailable 之间存在差异\x9d 和 \xe2\x80\x9c 对于导入者\xe2\x80\x9d 是可访问的。但从实际角度来看,这有什么区别呢?作为指导,我什么时候将某些内容放入私有模块片段中,什么时候不导出它?

\n

(突出显示我的内引号。)

\n

c++ c++20 c++-modules

6
推荐指数
1
解决办法
484
查看次数