我想在Visual Studio中使用C ++ 20模块,但是我的一个项目使用的是Magick ++,它在“ magick ++。h”中定义了struct一个char*名为“ module” 的成员:
Run Code Online (Sandbox Code Playgroud)typedef struct _MagickInfo { char *name, *description, *version, *mime_type, *note, *module; /* offending member here */ /* ... other members ... */ } MagickInfo;
我可以告诉编译器不要在特定的#include中处理“模块”吗?
在P1881提案中,提出了 C++ 代码的epoch(在模块级别)的概念。此类功能可以允许在模块级别自定义 C++ 语法和 C++ 行为,而不必破坏向后兼容性。提案中给出了更详细的动机。
版本 1:没有时代,一切都编译正常
module ParticleMovement;
export void move(Particle&, float x, float y);
void moveExample()
{
Particle p{};
move(p, 3.42, 2.49); // OK
}
Run Code Online (Sandbox Code Playgroud)
版本 2 :(epoch 2023假设在其中禁用隐式转换),代码格式错误:
epoch 2023; // Module-level switch
module ParticleMovement;
export void move(Particle&, float x, float y);
void moveExample()
{
Particle p{};
move(p, 3.42, 2.49); // Compilation error
move(p, 3.42f, 2.49f); // OK, no implicit conversions
}
Run Code Online (Sandbox Code Playgroud)
这绝对看起来是一个有趣的提议,并且与简单地指定 compile 开关非常不同 …
在重构我的项目以与模块一起使用之前,我编写了一个测试项目,ExImMod看看是否可以按照模块文档中的广告分离出声明和定义。对于我的项目,我需要将声明和定义保存在单独的翻译单元 (TU) 中,根据模块文档,这也是可能的。我不想使用模块分区。
不幸的是,我的测试ExImMod项目表明它们不能完全分离,至少对于 Visual Studio 2022 (std:c++latest) 编译器 (VS22) 来说是这样。
这是我的主要测试程序:
// ExImModMain.cpp
import FuncEnumNum;
import AStruct;
int main()
{
A a;
a.MemberFunc();
}
Run Code Online (Sandbox Code Playgroud)
A 的成员函数MemberFunc()在此声明:
// AStruct.ixx
// module; // global fragment moved to AMemberFunc.cppm (Nicol Bolas)
// #include <iostream>
export module AStruct; // primary interface module
export import FuncEnumNum; // export/imports functionalities declared in FuncEnumNum.ixx and defined in MyFunc.cppm
#include "AMemberFunc.hxx" // include header declaration
Run Code Online (Sandbox Code Playgroud)
其中包括“AMemberFunc.hxx”声明和定义:
// AMemberFunc.hxx
export struct A …Run Code Online (Sandbox Code Playgroud) 我正在尝试学习 C++20 功能附带的模块的概念。SubModule 和 ModulePartition 的概念让我很困惑。它们基本上都完成相同的工作,但我无法决定何时、在什么条件下使用哪一个。
你能准确地向我解释一下其中的区别吗?
我有两个文件 Interface.cppm(主模块接口单元)和 main.cpp。我没有该模块的任何其他模块单元。
在Interface.cppm中,我有以下内容
module;
#include <cstdint>
export module Interface;
import <algorithm>;
import <iostream>;
import <memory>;
import <sstream>;
import <string>;
import <tuple>;
import <type_traits>;
import <vector>;
//Code that this interface exports and
//implementation details.
Run Code Online (Sandbox Code Playgroud)
我是 main.cpp,我有以下代码:
import Interface;
import <iostream>;
import <memory>;
import <string>;
int main(){
//Using the contents of Interface module
}
Run Code Online (Sandbox Code Playgroud)
我预编译了标头单元并将它们放在名为 header-units 的文件夹中。然后我使用以下命令编译我的代码:
clang++ -std=c++20 Interface.cppm -fmodule-file=./header-units/algorithm.pcm -fmodule-file=./header-units/iostream.pcm --precompile -fmodule-file=./header-units/memory.pcm -fmodule-file=./header-units/sstream.pcm -fmodule-file=./header-units/string.pcm -fmodule-file=./header-units/tuple.pcm -fmodule-file=./header-units/type_traits.pcm -fmodule-file=./header-units/vector.pcm -fmodule-file=./header-units/unordered_map.pcm -o Interface.pcm //This works fine
clang++ -std=c++20 main.cpp -fmodule-file=Interface.pcm -fmodule-file=./header-units/iostream.pcm -fmodule-file=./header-units/string.pcm …Run Code Online (Sandbox Code Playgroud) 一般来说,使用函数模板会使编译时间显着延长。
一位朋友建议我检查模块(C++20)进行优化。
我认为这根本不会影响编译速度。
我不知道如何测试这个,所以我在这里问。
下面的代码会以某种方式神奇地优化构建过程吗?
定义仍然需要创建和编译,所以不会有任何区别?
数学.xxx:
module;
#include <typeinfo>
export module math;
import <iostream>;
export
template<typename T>
T square(T x) {
std::cout << typeid(T).name() << std::endl;
return x * x;
}
Run Code Online (Sandbox Code Playgroud)
主程序
import math;
void main() {
square(int());
square(double());
}
Run Code Online (Sandbox Code Playgroud) 在C ++中,模块被标准化以解决#include膨胀等问题。C ++中的编译器必须解析太多。
而且,由于C ++可以高效地内联存储数据,因此即使调用者也必须知道对象的内存布局。
即将发布的模块标准是否解决了这个问题?
例:
class GLWin {
private:
GLFWwindow* win;
glm::mat4 projection;
...
};
Run Code Online (Sandbox Code Playgroud)
包含指向内部实现的指针的对象可以通过空声明来解耦,即:
GLFWwindow类;
但是,如果出于性能考虑,我们将mat4对象包含在窗口内,那么我们需要知道大小(当前意味着包含定义),并引入一个头文件,该头文件通常由于级联包括而非常大。模块中是否有任何机制可以隐藏细节并允许为对象保留正确的空间,同时又使它像指针一样不透明?
我正在尝试 C++20,以更好地了解它们在实践中的工作原理。我了解了module :private可用于将接口与实现分离的片段,同时将两者保留在同一个文件中。这似乎适用于标准函数,但不适用于模板函数。
我有以下文件:
// File "main.cpp"
#include <iostream>
import mymodule;
int main()
{
std::cout << "greeting(): " << mymodule::greetings() << std::endl;
int x = 1;
int y = 2;
std::cout << "add(x, y): " << mymodule::add(x, y) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
// File "mymodule.ixx"
module;
#include <string>
// declare interface
export module mymodule;
export namespace mymodule {
template<typename T>
T add(T x, T y);
std::string greetings();
}
// implement interface
module :private;
std::string mymodule::greetings() {
return "hello";
} …Run Code Online (Sandbox Code Playgroud) 以下测试程序
import std;
int main() {}
Run Code Online (Sandbox Code Playgroud)
编译为gcc-14
/usr/local/bin/g++ -g -std=c++23 -fconcepts -fmodules-ts -O3 -Wall -Wextra test400.cc --output test400
Run Code Online (Sandbox Code Playgroud)
给出以下错误:
std: error: failed to read compiled module: No such file or directory
std: note: compiled module file is 'gcm.cache/std.gcm'
std: note: imports must be built before being imported
std: fatal error: returning to the gate for a mechanical issue
Run Code Online (Sandbox Code Playgroud)
标准库模块std应该是可用的,但显然不是。
std除了标头单元之外:是我自己创建模块的方法吗?
Visual Studio 2019 不会尝试编译我的 .cxx 或 .ixx 文件。这是我的 .cxx 文件:
export module greetings;
import std.core;
export std::string get_greeting_text()
{
return "Hello, World!";
}
Run Code Online (Sandbox Code Playgroud)
这是主要的:
import std.core;
import greetings;
int main()
{
std::cout << get_greeting_text() << '\n';
}
Run Code Online (Sandbox Code Playgroud)
我确实设置了这些标志:/std:c++latest, /experimental:module. 错误信息是
C:\...\main.cpp(2,17):error C2230: could not find module 'greetings'
C:\...\main.cpp(6,2): error C3861: 'get_greeting_text': identifier not found
Run Code Online (Sandbox Code Playgroud)
...但我没有看到任何关于尝试编译 greetings.cxx 的内容,所以这一定是问题所在。将其更改为 .ixx 无效。有什么解决办法?
我正在尝试将 C++ 模块 TS 与 clang 一起使用。
我创建了两个文件:
// foo.cppm
export module foo;
export void test() {
}
Run Code Online (Sandbox Code Playgroud)
和
// bar.cpp
import foo;
int main() {
test();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我foo.cppm用这个命令编译
clang++ --std=c++17 -fmodules-ts --precompile foo.cppm -o foo.pcm
Run Code Online (Sandbox Code Playgroud)
它编译没有错误并创建一个foo.pcm文件,但是当我尝试使用此命令编译二进制文件时:
clang++ --std=c++17 -fmodules-ts -fprebuilt-module-path=. -fmodule-file=foo.pcm bar.cpp
Run Code Online (Sandbox Code Playgroud)
它打印一个错误:
/tmp/bar-f69a1f.o: In function `main':
bar.cpp:(.text+0x10): undefined reference to `test()'
Run Code Online (Sandbox Code Playgroud)
我用 clang 7 trunk 和 clang 6 尝试过。我也尝试了不同的std选项和这个命令:
clang++ --std=c++17 -fmodules-ts -fmodule-file=foo.pcm bar.cpp -o bar
Run Code Online (Sandbox Code Playgroud)
没有任何帮助。
有趣的是,如果一个模块使用其他模块的符号,clang 会编译这些模块。所以据我所知,问题是在链接阶段。
有什么问题?