现在是 2020 年,C++20 以及期待已久的 C++ 模块功能即将到来。但是在看了一些关于 CppCon 的演讲后,我发现 C++ 模块处于一个奇怪的地方,尤其是对于 Linux 包管理器(pacman、apt、emerge 等...)
据我所知,C++ 模块是
我的问题是,在所有滚动发布发行版中,编译器一直在更新,用户可能有自己的编译器版本。目前可以只更新编译器或更新libstdc++
. 但是对于模块,似乎建议libstdc++
在编译器更新时必须更新。
当编译器更新时,包管理器将如何处理更新,例如 STL?我不认为为每个版本的编译器构建每个版本的 STL 模块是可行的。用户必须构建自己的 STL 模块也不是一个好主意。
c++ dependency-management package-management c++20 c++-modules
考虑以下三个方面struct
:
class blub {
int i;
char c;
blub(const blub&) {}
};
class blob {
char s;
blob(const blob&) {}
};
struct bla {
blub b0;
blob b1;
};
Run Code Online (Sandbox Code Playgroud)
在int
4 字节的典型平台上,大小、对齐方式和总填充1如下:
struct size alignment padding
-------- ------ ----------- ---------
blub 8 4 3
blob 1 1 0
bla 12 4 6
Run Code Online (Sandbox Code Playgroud)
blub
和blob
成员的存储之间没有重叠,即使大小 1blob
原则上可以“适合” blub
.
C++20 引入了no_unique_address
属性,它允许相邻的空成员共享相同的地址。它还明确允许使用一个成员的填充来存储另一个成员的上述场景。来自cppreference(强调我的):
指示此数据成员不需要具有与其类的所有其他非静态数据成员不同的地址。这意味着如果成员有一个空类型(例如无状态分配器),编译器可能会优化它以不占用空间,就像它是一个空基一样。如果该成员不为空,则其中的任何尾部填充也可以重新用于存储其他数据成员。
事实上,如果我们在 上使用这个属性blub b0
,大小会bla …
我正在寻找一种方法来从模板函数中的其他 lambda 中识别空的(无捕获的)lambda。我目前正在使用 C++17,但我也对 C++20 的答案感到好奇。
我的代码如下所示:
template<typename T>
auto func(T lambda) {
// The aguments of the lambdas are unknown
if constexpr (/* is captureless */) {
// do stuff
}
}
Run Code Online (Sandbox Code Playgroud)
C++ 标准(17 或 20)是否保证可转换为函数指针的无捕获 lambda 也会使std::is_empty
yield 为真?
以这段代码为例:
auto a = []{}; // captureless
auto b = [c = 'z']{}; // has captures
static_assert(sizeof(a) == sizeof(b)); // Both are the same size
static_assert(!std::is_empty_v<decltype(b)>); // It has a `c` member
static_assert(std::is_empty_v<decltype(a)>); // Passes. It is guaranteed? …
Run Code Online (Sandbox Code Playgroud) 我想使用 c++20 中可用的头文件。
我正在使用最新版本的 cmake。
我的 CMakeFiles 看起来像
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_BUILD_TYPE debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20")
Run Code Online (Sandbox Code Playgroud)
我使用 clang 9 作为我的编译器。
但是,在包含以下内容时出现以下错误:
fatal error: 'format' file not found
#include <format>
Run Code Online (Sandbox Code Playgroud)
我也使用了标志-std=c++2a
,但没有效果。简而言之,我觉得我在这里错过了一些重要的东西。我对 cmake 有点陌生,有什么帮助吗?
从 C++20 开始,我们可以有:
constexpr bool is_little_endian = std::endian::native == std::endian::little;
Run Code Online (Sandbox Code Playgroud)
如果可用,我希望有执行此操作的代码,否则执行运行时检测。这可能吗?
也许代码看起来像:
template<bool b = std_endian_exists_v> constexpr bool is_little_endian;
template<> constexpr bool is_little_endian<true> = std::endian::native == std::endian::little;
template<> constexpr bool is_little_endian<false> = runtime_detection();
Run Code Online (Sandbox Code Playgroud)
我知道__cplusplus
通过预处理器进行测试是可能的,但是 C++20 中的编译器阶段在各个阶段都支持,因此这在任一方向都不是可靠的指标。
考虑以下简单的协程,它跟踪其构建和销毁:
#include <coroutine>
#include <iostream>
struct simple {
static inline int x = 0;
int id = 0;
simple() : id{ x++ } { std::cout << id << " constructed\n"; }
simple(simple&&) : id{ x++ } { std::cout << id << " move constructed\n"; }
~simple() { std::cout << id << " destructed\n"; }
struct promise_type {
simple get_return_object() { return {}; }
void return_void() {}
void unhandled_exception() { std::terminate(); }
auto initial_suspend() noexcept { return std::suspend_never{}; }
auto final_suspend() …
Run Code Online (Sandbox Code Playgroud) 我发现了一种情况,代码在 C++17 下编译成功,但在 C++20 下编译失败。
这阻止了我们将现有的代码设计升级到更新的标准。
为什么这不能在 C++20 下编译?这似乎是对向后兼容性的奇怪破坏。
当我尝试为模板类专业化的构造函数/析构函数授予友好关系时会发生错误。
我正在使用带有 Ninja 的 MSVC 进行编译。
在 C++17 下编译成功。
在 C++20 下,我收到以下错误:
error C2838: '{ctor}': illegal qualified name in member declaration
error C2838: '{dtor}': illegal qualified name in member declaration
Run Code Online (Sandbox Code Playgroud)
这是在 C++20 下导致错误但在 C++17 下编译成功的代码的简化复制:
template<typename T, int V> class B {};
// specialization of class B
template<typename T> class B<T, 0> {
private:
T _t; // private data member
public:
constexpr inline B(T* p, int i) noexcept; // B constructor …
Run Code Online (Sandbox Code Playgroud) #include <type_traits>
template<typename T>
struct IsComplete final
: std::bool_constant<requires{sizeof(T);}>
{};
int main()
{
struct A;
static_assert(!IsComplete<A>::value); // ok
struct A{};
static_assert(IsComplete<A>::value); // error
}
Run Code Online (Sandbox Code Playgroud)
我预计第二个static_assert
应该是真的,因为 A 现在是一个完整的类型。
为什么 C++20 的要求表达式的行为不符合预期?
我想要一个concept
需要任意向量作为返回类型:
template<typename T>
concept HasVector = requires (T t) {
{ T.vec() } -> std::same_as<std::vector<int>>; //works
{ T.vec() } -> std::same_as<std::vector<foo>>; //want to put something arbitrary in here
}
Run Code Online (Sandbox Code Playgroud)
这样我们就会有如下内容:
class A {
std::vector<int> vec() { /* ... */}
}
class B {
std::vector<double> vec() { /* ... */}
}
static_assert(HasVector<A>);
static_assert(HasVector<B>);
Run Code Online (Sandbox Code Playgroud)
此外,要求一个向量作为返回类型会更好,其值类型满足其他一些概念,即
template<typename T>
concept Arithmetic = // as in the standard
template<typename T>
concept HasArithmeticVector = requires (T t ) {
{ T. vec() } -> …
Run Code Online (Sandbox Code Playgroud) 鉴于以下设置:
// ***** Library Code *****
#include <concepts>
template <std::invocable CbT>
struct delegated {
explicit constexpr delegated(CbT cb) : cb_(std::move(cb)) {}
private:
[[no_unique_address]] CbT cb_;
};
// ***** User Code *****
#include <iostream>
namespace {
inline constexpr void func() {}
}
struct MyFunc {
constexpr void operator()() const {}
};
int main() {
void (*func_ptr)() = func;
auto from_func = delegated{func};
auto from_func_ptr = delegated{func_ptr};
auto from_lambda = delegated{[](){}};
auto from_functor = delegated{MyFunc{}};
std::cout << "func: " << sizeof(from_func) << …
Run Code Online (Sandbox Code Playgroud) c++ ×10
c++20 ×10
templates ×2
c++-concepts ×1
c++-modules ×1
c++17 ×1
cmake ×1
constexpr ×1
endianness ×1
format ×1
friend ×1
gcc ×1
lambda ×1
sfinae ×1
type-traits ×1
vector ×1