据我所知,pimpl 习惯用法将私有实现隐藏在前向声明的符号名称后面,以便可以在私有 cpp 模块中声明和使用它。
示例: https: //cpppatterns.com/patterns/pimpl.html
据我所知,因为 pimpl 类 hosint 需要了解其结构(大小、对齐方式),所以 pimpl 必须通过某种指针是间接的。
(或分配为足够大小的块,然后移动/创建到稍后通过强制转换重新解释的位置。)
即将推出的模块规范是否以任何方式解决这个问题?
我如何在Clang中使用C++模块中给出的基本示例?适合我,但不导入标准库(例如via import std.stdio;); 在浏览了http://clang.llvm.org/docs/Modules.html之后,目前尚不清楚如何在C++模块中使用标准库,例如:
// foo.cppm:
export module foo;
// works: #include <stdio.h>
// none of these work:
import std.stdio;
import std.io;
import std;
export void test_foo(){
printf("hello world\n");
}
Run Code Online (Sandbox Code Playgroud)
这给出了一个错误:
clang++ -std=c++17 -fmodules-ts --precompile foo.cppm -o foo.pcm
foo.cppm:4:8: fatal error: module 'std.stdio' not found
注意:
clang++ --version
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.4.0
我在OSX上.我也试过brew install llvm的clang也没用.
制作这样的作品最简单的方法是什么?
声明全局常量可能很方便,但在 C++ 中并不容易。例如,请参阅Fluent C++ 最近的这篇文章。它主要解释了如何做到这一点,但没有提及 C++20 模块。
在命名空间级别的常规头文件中,我将声明一个如下常量:
// Constants.h
inline constexpr int Count = 42;
inline const std::vector<int> Numbers = { 1, 2, 3 }; // cannot use constexpr
Run Code Online (Sandbox Code Playgroud)
这里我需要inline,因为这些符号可能包含在多个翻译单元中。IIUC,导出符号的模块定义单元,是一个单独的翻译单元。所以我简单地声明如下:
// Constants.ixx
export module constants;
export constexpr int Count = 42;
export const std::vector<int> Numbers = { 1, 2, 3 }; // cannot use constexpr
Run Code Online (Sandbox Code Playgroud)
这是正确的做法,还是我错过了什么?
到目前为止,在我看来,在 C++ 模块接口中包含几乎所有 libstdc++ 标头都会导致 clang 14.0.0 和与 GCC 11.2.0 捆绑在一起的 libstdc++ 出现编译错误。我想知道我是否做错了什么,或者这是否还不受支持。(我发现Clang 模块支持是“部分”的,但无法找到已实现的内容和未实现的内容。)
这是一个简单的模块示例,我在 Linux 中使用 clang-14,并与 libstdc++ 链接。它演示了 libstdc++ 标头可以在模块实现中使用,但此示例未在模块接口中 #include 任何内容:
// mod_if.cc
export module mod;
export int foo();
// mod.cc
module;
#include <iostream>
module mod;
int foo() {
std::cout << "Hello world from foo()" << std::endl;
return 42;
}
// use.cc
import mod;
#include <iostream>
int main() {
std::cout << foo() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
这有效:
$ CXXFLAGS="-std=c++20 -fmodules -fprebuilt-module-path=prebuilt"
$ …Run Code Online (Sandbox Code Playgroud) -fmodules当使用下面所示的命令进行编译时,以下简单的测试用例文件给了我一个编译时错误,提示来自 Clang 的 github 镜像的“master” 。我想知道这是否是 Clang 的新实验性模块功能的一个错误——可能是标准库模块映射的实现问题——或者我是否做错了什么。-fbuiltin-module-map如果我添加到命令中,错误仍然出现。stdint.h有趣的是,如果我替换为 ,该错误就不再出现cstdint。
#include <stdint.h>
uint64_t foo;
Run Code Online (Sandbox Code Playgroud)
这是我的编译命令,带有错误消息:
anhall@leviathan: /Users/anhall/impersonal/code/llvm-reflexpr/install/bin/clang++ -o module-uint64_t-test.o -c module-uint64_t-test.cpp --std=c++1z -fmodules
module-uint64_t-test.cpp:3:1: error: missing '#include <_types/_uint64_t.h>'; declaration of 'uint64_t' must be imported from module 'Darwin.POSIX._types._uint64_t' before it is
required
uint64_t foo;
^
/usr/include/_types/_uint64_t.h:31:28: note: previous declaration is here
typedef unsigned long long uint64_t;
Run Code Online (Sandbox Code Playgroud)
有关我正在使用的构建的信息:它来自 Matus Chochlik 的 github Clang 镜像的分支;但我设置为与原始 clang git 镜像中“master”的(当时)头相对应的提交(换句话说,它不包括来自 Matus Chochlik 的功能“reflexpr”分支的提交):
anhall@leviathan: /Users/anhall/impersonal/code/llvm-reflexpr/install/bin/clang++ -v
clang version 4.0.0 …Run Code Online (Sandbox Code Playgroud) 鉴于以下模块
// mod.cpp
export module mod;
export template<typename T>
struct something
{
constexpr something(T){}
};
export template<typename T>
constexpr auto make_something(T t)
{
return something{t}; // uses CTAD
}
Run Code Online (Sandbox Code Playgroud)
用clang编译:
clang++ -std=c++20 -stdlib=libc++ -fmodules -c -Xclang -emit-module-interface -o mod.pcm mod.cpp
以及以下应用程序代码:
import mod;
int main()
{
constexpr auto x = make_something(7);
}
Run Code Online (Sandbox Code Playgroud)
编译:
clang++ -std=c++20 -stdlib=libc++ -fmodules -fimplicit-modules -fimplicit-module-maps -fprebuilt-module-path=. main.cpp
后者失败并显示以下错误消息:
In file included from main.cpp:1:
mod.cpp:13:12: error: no viable constructor or deduction guide for deduction of template arguments …Run Code Online (Sandbox Code Playgroud) 我正在尝试将 C++20 模块与类一起使用。但我不断从编译器中收到此错误:
collect2.exe:错误:ld 返回 1 退出状态
这是我用来编译文件的编译器指令:
g++ -std=c++20 -fmodules-ts -o 主airline_ticket.cpp main.cpp
这是airline_ticket.cpp的代码:
module;
#include <iostream>
export module airline_ticket;
export class AirlineTicket
{
public:
AirlineTicket()
{
name = "Unknown";
km = 0;
isPremium = false;
};
int getKm() { return km; };
void setKm(int distance) { km = distance; };
std::string getName() { return name; };
void setName (std::string nameString) { name = nameString; };
bool getIsPremium() { return isPremium; };
void setIsPremium(bool status) { isPremium = status; …Run Code Online (Sandbox Code Playgroud) 这个问题可能太宽泛了,但最近确实让我很高兴:
我最近发现了现代 C++ 中的模块: https://en.cppreference.com/w/cpp/language/modules
但我真的不明白他们的目的以及何时使用它而不是命名空间或只是库头?
在提供的示例中,他们现在使用import <iostream>;代替include <iostream>;,使用其中一种与另一种有什么区别?哪一个是首选?
他们说“模块与名称空间正交”?这是什么意思?
关于开发的指导方针是什么,我们现在应该避免标题和东西吗?
例如:
你好世界.cpp
export module helloworld; // module declaration
import <iostream>; // import declaration
export void hello() // export declaration
{
std::cout << "Hello world!\n";
}
Run Code Online (Sandbox Code Playgroud)
主程序
import helloworld; // import declaration
int main()
{
hello();
}
Run Code Online (Sandbox Code Playgroud)
相对
helloworld.h / helloworld.cpp
include <iostream>;
namespace ns
{
void hello();
}
#include "helloworld.h";
void ns::hello()
{
std::cout << "Hello world!\n";
}
Run Code Online (Sandbox Code Playgroud)
主程序
#include "helloworld.h";
int main()
{ …Run Code Online (Sandbox Code Playgroud) 我正在 C++ 中测试模块,但不断收到以下错误:
linker input file unused because linking not done
和
ld: file not found: CMakeFiles/TestModule.dir/src/A.cppm.o
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
Run Code Online (Sandbox Code Playgroud)
这是我编写的以下代码:
模块:A.cppm
ld: file not found: CMakeFiles/TestModule.dir/src/A.cppm.o
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
Run Code Online (Sandbox Code Playgroud)
我的 main.cpp 文件:
export module A;
export namespace Lib_A {
int getNumberOne() { return 1; }
int getNumberTwo() { return 2; }
}
Run Code Online (Sandbox Code Playgroud)
现在我的 CMakeFile:
cmake_minimum_required(VERSION 3.24)
project(TestModule)
set(CMAKE_CXX_STANDARD 20)
add_executable(TestModule src/main.cpp …Run Code Online (Sandbox Code Playgroud) 以这段代码为例(演讲 LLVM Optimization Remarks - Ofek Shilon - CppCon 2022,21:28):
void somefunc(const int&);
int whateva();
void f(int i, int* res)
{
somefunc(i);
i++;
res[0] = whateva();
i++;
res[1] = whateva();
i++;
res[2] = whateva();
}
Run Code Online (Sandbox Code Playgroud)
由于somefunc和whateva的主体不可用于此翻译单元(从现在起为 TU)中的编译器,因此可能会错过很多优化机会。
如果您的项目仅使用 C++20 模块,这个问题是否“已解决”?据我所知,在使用模块时,编译器会生成一些包含有关模块的元数据的文件,类似于预编译头,我们将其称为预编译模块,并且这些预编译模块必须包含在任何其他模块中(在命令行上)导入它们。
这是否意味着“翻译单元边界悲观化”(我编了这个名字;我不知道它是否有一个)在使用模块时肯定消失了,因为所有模块都会看到所有主体(感谢附加的预编译模块) )每个函数?
换句话说,如果您的项目不使用任何单个#include,除了动态链接库之外,新的“编译器可见性边界”(忽略 LTO)是什么?