标签: c++-modules

联合未定义结构中的C++模块模板 - VC 2017

我正在尝试使用Visual Studio 2017的模块中的模板实验模块.这是我想要制作的模块的简化示例

// MyModule.ixx
module MyModule;

export
{
    template<typename T>
    struct Struct_1
    {
        T value;
    }

    template<typename T>
    struct Struct_2
    {
        union
        {
            T data[1];
            Struct_1<T> x;
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是我试图使用模块和模板结构的方法

// main.cpp
import std.core;
import MyModule;

int main(int argc, char* argv[])
{
    Struct_2<float> s;
    std::cout << s.data[0];

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译给出以下内容: error C2079: 'Struct_2::x' uses undefined struct 'Struct_1<T>

我知道模块是一个实验性功能,但是,当不使用模块时,定义像这样的结构工作正常.它说Struct_1<T>是未定义的,这是否意味着我需要以某种方式显式实例化模板?

我的编译器命令行如下所示:

cl /utf-8 /experimental:module MyModule.ixx /std:c++latest /W3 /Zi /MDd /EHsc main.cpp /link /OUT:test.exe /INCREMENTAL:NO

任何帮助表示赞赏.

UPDATE

我认为这是某种MSVC编译器错误.我使用Clang编译了相同的代码,它工作正常.Clang模块文件看起来与上面相同,但文件扩展名为.cppm,而顶部则为: …

c++ module c++20 c++-modules visual-studio-2017

5
推荐指数
0
解决办法
135
查看次数

C++模块是否会导致ODR违规?

N4720 C++模块草案中,[basic.def.odr]/6说:

[......] 对于拥有出口申报单的实体,该实体只应有一个定义; 仅当模块的抽象语义图包含实体的定义时才需要诊断.[注意:如果定义不在接口单元中,则最多一个模块单元可以拥有并使用该定义. - 尾注] [...]

根据我的理解,实际上模板只有一次机会被编译器解析一次,与当前事态形成对比(每个翻译单元的定义都有一个精确的副本).这对于具有类似情况的其他实体也是有效的,例如内联函数/变量.

我的问题来自这样一个事实:由于每个翻译单元最多只能有一个实体定义(如[basic.def.odr]/1中所述),因此在TU中对实体进行不同的定义是未定义的行为. .并且,由于导出的实体在整个编译单元中只有一个定义(使未实现的定义对于它们的实现单元是唯一的),从我的角度来看,定义错误即使不是不可能也是更难的.

最后,简单地说:将(或确实或应该)模块的使用使得不可能违反ODR规则,或者更难以出错?

c++ one-definition-rule c++-modules

5
推荐指数
1
解决办法
249
查看次数

C ++模块和动态链接的预期关系是什么?

C ++模块TS为消除预处理器,缩短编译时间,并为至少非模板代码至少支持C ++中更健壮,模块化的代码开发提供了绝佳的工具。

底层机制可控制普通程序中符号的导入和导出。

但是,开发用于两种动态加载的库存在一个主要问题:启动时加载和运行时加载。此问题涉及从库中导出符号,通常会在可见性方面进行讨论。

通常,并非所有用于构建动态链接库的翻译单元的外部符号都应对用户可见。此外,在运行时加载时,尤其是在使用插件概念加载时,必须从许多同时加载的库中导出同一符号。

在Windows上使用语言扩展

 __declspec(dllexport)
 __declspec(dllimport)
Run Code Online (Sandbox Code Playgroud)

附加在源代码中作为符号的属性,最近在unix平台上的gcc和clang系统上,

__attribute__((visibility("default")))
__attribute__((visibility("hidden"))) 
Run Code Online (Sandbox Code Playgroud)

旨在支持打算由图书馆公开的符号的提供和使用。使用它们是复杂且混乱的:在Windows上,在编译库时必须使用宏来导出符号,而在使用它们时则要导入它们。在unix平台上,必须将可见性设置为默认设置,以同时导出和导入符号,由编译器根据是否找到定义来决定其自身:必须使用以下命令调用编译器:

-fvisibility=hidden 
Run Code Online (Sandbox Code Playgroud)

开关。静态链接不需要export / import属性,可能应该将其宏化为空字符串。编写代码并摆弄构建系统,以使所有这些工作正常进行,尤其是考虑到#include必须在库翻译单元的编译过程中设置正确的符号可见性,这非常困难,存储库中所需的文件结构混乱,源代码杂乱无章与宏,总的来说,整个事情都是一场灾难。几乎所有开放源代码存储库都无法正确导出符号以进行动态链接,并且大多数程序员都不知道动态库代码结构(使用两级名称空间)与静态链接完全不同。

可以在此处看到如何执行此操作的示例(希望正确):

https://github.com/calccrypto/uint256_t

该存储库曾经有2个标头和2个实现文件,内置库的用户将看到2个标头。现在有7个头文件和2个实现文件,内置库的用户将看到5个头文件(其中3个扩展名include表示不直接包含这些文件)。

因此,在经过漫长的解释之后,问题是:最终的C ++模块规范是否有助于解决动态链接符号的导入和导出问题?我们可以期望能够开发共享库而不会用供应商特定的扩展名和宏来污染我们的代码吗?

c++ c++-modules

5
推荐指数
1
解决办法
378
查看次数

C++ 头单元导入语法

在当前的 C++ 草案(2019 年 8 月)中,pp-import http://eel.is/c++draft/cpp.import#nt:pp-import的语法允许pp-tokensheader-nameheader-name-tokens.

该部分的当前版本是P1703的结果:“Recognizing Header Unit Imports Requires Full Preprocessing”。在此提案引起的变化之前,语法仍然允许预处理header-name或之后的标记标记header-name-tokens,但以 a 的形式pp-import-suffix。(第[cpp.module] P1103)。

在这种情况下允许额外的、未使用的预处理令牌背后的原因是什么?

谢谢你。

c++ language-lawyer c++20 c++-modules

5
推荐指数
1
解决办法
440
查看次数

C++ 模块的两步编译?

Clang 和 GCC(也许还有 MSVC?)目前正在使用两步编译来实现其模块:

  • 生成 BMI/CMI(MSVC 的 IPR,如果它仍然这样做?)以供其他人的导入使用。
  • 生成要提供给链接器的目标文件。

生成 BMI/CMI 但不生成目标文件的模块似乎有一些可能的用途,例如仅导出用于条件编译的类型或 constexpr 变量的模块。

据我从标准中可以理解,没有任何规定我必须生成/链接对象文件。所以我想知道我是否错过了关于使用这样的模块的一些明显的东西,以及我们是否期望工具支持这种“构建为模块,而不是构建为对象”工作流程?

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

5
推荐指数
1
解决办法
1143
查看次数

什么是 clang 编译的模块 pcm 文件?

我正在查看 clang 模块的驱动程序测试用例:https : //github.com/llvm-mirror/clang/blob/master/test/Driver/modules.cpp

它包括生成 .pcm.o 文件的步骤。我想知道它们是干什么用的。

给定一个 c++20 模块

// a-m.cc
module;
#include <iostream>
export module a;
export void do_a() { std::cout << "A\n"; }
Run Code Online (Sandbox Code Playgroud)

您可以使用编译它

clang++ -std=c++20 -x c++-module --precompile a-m.cc -o a.pcm
Run Code Online (Sandbox Code Playgroud)

它生成预编译的模块文件a.pcm

但是也有将 .pcm 文件编译为 .o 文件的步骤。

从驱动程序测试

clang++ -std=c++20 a.pcm -S -o a.pcm.o
Run Code Online (Sandbox Code Playgroud)

如何使用 .pcm.o 文件?

如果我写一个主程序

// main.cc
import a;

int main() {
    do_a();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译

clang++ -std=c++20 -c main.cc -fmodule-file=a=a.pcm
Run Code Online (Sandbox Code Playgroud)

然后尝试与 .pcm.o 链接,我得到

clang++ main.o …
Run Code Online (Sandbox Code Playgroud)

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

5
推荐指数
1
解决办法
207
查看次数

使用gcc-11构建c++20模块时如何修改gcm.cache路径?

我试图让xmake支持 gcc-11 来构建 c++20 模块,但我遇到了一些问题。

gcm.cachegcc-11默认会在当前目录生成目录。如何修改这个默认路径到指定的其他目录?

我知道clang有一个-fmodules-cache-path=修改模块缓存路径的选项,但是我没有找到gcc的类似选项。

有人知道吗?谢谢

c++ gcc c++-modules xmake

5
推荐指数
1
解决办法
801
查看次数

"import std;"的目的 在C++中

我在cppdepend网站上看到了以下一小段代码.

import std; // Module import directive.
int main() 
{
    std::cout<<"Hello World\n";
}
Run Code Online (Sandbox Code Playgroud)

那么,import std;C++ 的目的是什么?如何使用import std;而不是using namespace std;在C++中?

我试图在G ++编译器中编译程序,但是我收到了一个错误.

c++ c++-modules

4
推荐指数
1
解决办法
802
查看次数

使用 clang 将 std lib 作为模块导入

我正在尝试使用 clang 中的模块,并希望将标准库包含为模块而不是包含。

目前我这样做

#include <iostream>
#include <string>
Run Code Online (Sandbox Code Playgroud)

看来您在 msvc 中应该能够导入标准库,例如

import std.core;
Run Code Online (Sandbox Code Playgroud)

然而,当使用 clang 时,这似乎没有实现,或者以另一种方式实现。

我的问题是:是否可以像微软建议的那样导入 stl-includes,或者是否可以将标准库包含映射到模块 somhow。

注意:我无法使用的原因#include <...>或者#import <...>是因为其他错误可能会导致其自身问题。所以我认为import std.core如果可能的话,获取或类似是现在要走的路。

ModernesCpp还提到了 std.core。

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

4
推荐指数
2
解决办法
731
查看次数

如何在 CLang C++ 下编译/使用头单元模块?

文档中说 CLang 中的模块支持是部分的。我在最近发布的 LLVM 12.0 中在 Windows 64 位下使用 CLang。

我成功地设法使用了常规模块(您通过 导入import modulename;)。

但我还没有设法创建和使用头单元模块,那些你通过import "header.hpp";. 你能建议如何用例子做到这一点吗?

为了尝试标题单元,我创建了下一个玩具文件:

你好.hpp

#include <vector>
Run Code Online (Sandbox Code Playgroud)

使用.cpp

import "hello.hpp";

int main() {
    std::vector<int> v(123);
}
Run Code Online (Sandbox Code Playgroud)

然后我成功(我希望)将头单元编译hello.hpp成 PCM 文件:

clang++ -std=c++20 -Xclang -emit-header-module -I. hello.hpp -o hello.pcm
Run Code Online (Sandbox Code Playgroud)

命令运行没有错误并产生hello.pcm. 如果您在没有-o标志的情况下运行上面的命令,hello.hpp.gch则会创建文件 。

然后我尝试编译use.cpp,但没有成功,不知何故它无法识别我的头单元和/或找不到相应的hello.pcm. 我想我错过了一些特殊的标志,这些标志表明编译器是头单元。使用了下一个命令:

clang++ -std=c++20 -fprebuilt-module-path=. -fmodule-file=hello.hpp=hello.pcm -I. use.cpp
Run Code Online (Sandbox Code Playgroud)

这给了编译错误:

use.cpp:1:8: error: header file "hello.hpp" (aka './hello.hpp') cannot be imported …
Run Code Online (Sandbox Code Playgroud)

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

4
推荐指数
1
解决办法
301
查看次数