MS Visual C++ 2015 Update 1 实现了模块提议.
以下是它的工作原理示例:
来源:
// c.ixx | // b.ixx | // a.cpp
module GM; | import GM; | import FM;
export void g() {} | module FM; | int main() { f(); }
| export void f() { g(); } |
Run Code Online (Sandbox Code Playgroud)
构建命令:
set CL=/EHsc /experimental:module # Default flags for cl.exe
cl.exe /c c.ixx # Produces c.obj, GM.ifc
cl.exe /c b.ixx # Depends on GM.ifc, produces b.obj, FM.ifc
cl.exe /c a.cpp # Depends on FM.ifc, …Run Code Online (Sandbox Code Playgroud) (有关我正在使用的特定版本的Boost和Clang的信息,请参阅问题的结尾)
使用新的实验性-fmodules功能在master/HEAD中编译Clang,使用下面显示的命令行选项编译以下文件时出现构建错误:
#include <iterator>
#include <boost/move/iterator.hpp>
Run Code Online (Sandbox Code Playgroud)
编译命令和错误:
anhall@leviathan: <path-to-clang-install-from-master>/bin/clang++ -o file.o -c file.cpp --std=c++1z -stdlib=libc++ -fmodules
In file included from file.cpp:2:
In file included from /usr/local/include/boost/move/iterator.hpp:27:
/usr/local/include/boost/move/detail/iterator_traits.hpp:60:17: error: reference to 'random_access_iterator_tag' is ambiguous
typedef std::random_access_iterator_tag iterator_category;
^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:438:30: note: candidate found by name lookup is 'std::__1::random_access_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY random_access_iterator_tag : public bidirectional_iterator_tag {};
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:34:8: note: candidate found by name lookup is 'std::random_access_iterator_tag'
struct random_access_iterator_tag;
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:71:17: error: reference to 'random_access_iterator_tag' is ambiguous
typedef std::random_access_iterator_tag iterator_category;
^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:438:30: …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Clang的“模块”功能,并且正在尝试编译以下代码:
export module a;
#include <new>
export void *foo()
{
return ::operator new(1, std::align_val_t(1));
}
export int main() {}
Run Code Online (Sandbox Code Playgroud)
当我尝试时clang++ -std=c++2a -pedantic-errors -fmodules-ts --precompile -x c++-module a.cpp -o a.pcm,我得到了
Run Code Online (Sandbox Code Playgroud)error: ISO C++ requires a definition in this translation unit for function 'operator new' because its type does not have linkage [-Werror,-Wundefined-internal-type] a.cpp:7:14: note: used here return ::operator new(1, std::align_val_t(1)); ^ 1 error generated.
删除-pedantic-errors修复了该错误,但是当我尝试使用链接生成的模块时clang++ -std=c++2a -fmodules-ts a.pcm -o a.exe,我得到了
Run Code Online (Sandbox Code Playgroud)Z:\Lander\msys2\tmp\a-cfaf65.o:a.pcm:(.text+0x10): undefined …
假设我们有模块接口源文件 foo.ixx,其中定义了模块 foo。我们用
import foo;
Run Code Online (Sandbox Code Playgroud)
在许多不同的 cpp 文件中。与传统头文件 foo.h 包含在许多不同的 cpp 文件中的情况相比,编译时间会减少吗?如果编译时间减少了,为什么会这样?
Bazel 不直接支持模块(请参阅问题 #4005)。
但是,可以为 bazel 提供定制的 CROSSTOOL。
来自https://docs.bazel.build/versions/0.22.0/crosstool-reference.html:
默认情况下,Bazel 会自动为您的构建配置 CROSSTOOL,但您可以选择手动配置它。
并且可以使用自定义规则扩展 bazel。
来自https://docs.bazel.build/versions/master/skylark/rules.html:
Bazel 本身内置了一些规则。这些原生规则,例如 cc_library 和 java_binary,为某些语言提供了一些核心支持。通过定义自己的规则,您可以为 Bazel 本身不支持的语言和工具添加类似的支持。
关于Bazel 模块问题的评论表明,即使没有本机支持,您也可以使用自定义 CROSSTOOL 来支持模块:
有关模块(仅适用于 clang)的所有内容都已经开源。唯一缺少的部分是使用它们并提供所有必要功能的 CROSSTOOL。
任何人都可以展示如何为 clang 编写自定义 CROSSTOOL 以及如何使用它为模块编写自定义 C++ 规则(例如cc_module),以便您可以执行以下操作:
编写一个基本模块
// helloworld.cc
module;
#include <stdio.h>
export module helloworld;
export void hello();
module :private;
void hello() { puts("Hello world!"); }
Run Code Online (Sandbox Code Playgroud)
使用模块
// main.cc
import helloworld;
int main() { hello(); }
Run Code Online (Sandbox Code Playgroud)
将零件集成到构建系统中
cc_module(
name = "helloworld",
srcs …Run Code Online (Sandbox Code Playgroud) 有没有一种方法可以将类定义(实现)拆分为多个模块单元?如果一个或多个类的方法足够大,可以放置在单独的源文件中,这会很有帮助。我看到的最好的解决方案可能是模块接口文件中的类声明及其在单独的模块实现文件中的方法定义之一。但它不起作用,因为编译器看不到类声明编译模块实现文件:
//module interface unit
export module test;
export class foo
{
void f();
};
//module implementation unit
module test;
void foo::f() {} // compiler doesn't know about foo class and its methods
Run Code Online (Sandbox Code Playgroud) 我正在创建一个库,并且 C++20 模块内有一个类模板,我想添加一个实例化,以减少使用我的库的每个项目的编译时间。
这些不同的实现是否等效,或者是否有更好的方法来实现?
1)
//mod.cpp
export module mod;
export template<typename T>
struct mystruct{ T i;};
export template class mystruct<int>;
Run Code Online (Sandbox Code Playgroud)
//mod.cpp
export module mod;
export template<typename T>
struct mystruct{ T i;};
template class mystruct<int>;
Run Code Online (Sandbox Code Playgroud)
//mod.cpp
export module mod;
export template<typename T>
struct mystruct{ T i;};
export extern template class mystruct<int>;
//mod_impl.cpp
module mod;
template class mystruct<int>;
Run Code Online (Sandbox Code Playgroud)
编辑:这个答案只说 2. 有效,但我的观点是 1. 和 3. 是否也等于 2.
我有以下文件:
#include <string>
#include <iostream>
int main() {
std::string ss = "aaaa";
ss += "aa";
std::cout << ss << "\n";
}
Run Code Online (Sandbox Code Playgroud)
当我像这样编译它时:g++-11 -o Testing2 Testing2.cpp -std=c++20,我得到了所需的输出。当我像这样编译它时:g++-11 -o Testing2 Testing2.cpp -std=c++20 -fmodules-ts,我收到运行时分段错误错误。
问题 1:这是 g++ 中的错误,还是我遗漏了什么?
我有几个类似的问题,一个与std::filesystem,一个与std::map。即使没有实际使用模块,代码也将无法正常工作。
问题2:上面的代码甚至没有使用模块。为什么 g++ 在-fmodules-ts启用和未启用时编译它的方式不同?
我在编写的一些基于模块的 C++ 代码中遇到“基类未定义”错误。我已将其简化为以下 MCVE。非模块等效项可以很好地编译。我不明白为什么这里的模块化代码会失败。请有人解释一下为什么我会收到错误,以及如果可能的话如何修复它。
这是模块接口单元 -
// mcve.ixx
export module mcve;
export class X
{
friend class F; // (1)
};
export
template<typename T>
class A
{
};
export class B: public A<X>
{
};
// (2)
export class F: public B
{
};
Run Code Online (Sandbox Code Playgroud)
以及显示报告编译器错误的位置的 cpp 文件。
// main.cpp
import mcve;
int main()
{
// X x; // (3)
// A<X> ax; // (4)
// F f; // (5)
B b; // error C2504: 'B': base class undefined
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,删除 …
我目前正在使用 C++ 模块,尝试对我们公司的代码 C++ 基础进行现代化改造,以使用模块来实现核心功能。特别是即将推出的 C++23std模块,作为预编译头的更好替代品,它看起来非常有趣。
所以我使用的是Visual Studio 2022 17.5 Preview 2.0,它对模块有初步支持std。顺便说一句,我遇到了编译器内部错误,我向Microsoft报告了这个错误。
在我们所有的 C++ 源文件中,现在都有一个import std;语句,而且效果很好。每个应该位于std命名空间中的标识符似乎都按预期导出。我测量到与之前使用预编译头相比,编译时间略有减少。
我发现,如果你,你在任何标准import std;C++ 头文件中都会遇到很多奇怪的编译错误,因为 Microsoft 编译器会感到困惑并抱怨重新定义。所以我小心翼翼地将它们全部删除。 #include <>
我的问题是,标准库中定义了一些宏(主要是在 C 兼容库中),这些宏显然没有导出,因为 C++ 模块在设计上从不导出宏。
我们的代码库使用的标准宏数量非常有限,但我认为很难避免它们。以下是它们的简短列表(不确定是否完整):
stdouterrnova_start, va_arg,va_end对于va_*宏,我#include <stdarg.h>和它在 VS 2022 上编译得很好,尽管它打破了我之前提到的规则。这可能是因为该标头几乎只有宏。但对于stdout和errno,我不知道该怎么办。
C++23 是否指定在导入模块时如何访问重要的标准宏,例如stdout或?有没有好的解决方法?errnostd