clang++ 12 是否支持 C++20 std::construct_at?
Does clang++ 12 support C++20 std::construct_at?
我正在使用最近批准的 C++20 标准功能 std::construct_at()
并试图更加熟悉它们...
我已经基于 example from CppReference.com:
构建了一个示例
#include <memory>
struct S {
int a;
int b;
};
int main() {
std::allocator<S> alloc;
S * s = alloc.allocate(1);
std::construct_at(s, 42, 43); // GCC 10.2 OK Clang 12 NOT
std::destroy_at(s);
alloc.deallocate(s, 1);
s = nullptr;
}
上面的代码可以在最新的稳定版 GCC 中正常构建:
gcc-10.2 test.cpp -std=c++2a -lstdc++
但我无法使用 Clang 12 (trunk) 或 10 (stable) 对其进行编译。
clang-12 test.cpp -std=c++20 -stdlib=libc++
错误:
test.cpp:11:5: error: no matching function for call to 'construct_at'
std::construct_at(s, 42, 43); // GCC 10.2 OK Clang 12 NOT
^~~~~~~~~~~~~~~~~
/usr/local/clang/bin/../include/c++/v1/memory:903:16: note: candidate template ignored: substitution failure [with _Tp = S, _Args = <int, int>]: no matching constructor for initialization of 'S'
constexpr _Tp* construct_at(_Tp* __location, _Args&& ...__args) {
^
1 error generated.
我是不是参数包用错了?
Clang C++20 feature list 好像没说支持?
我在 Clang 中尝试使用 GCC 工具链,结果相同:--gcc-toolchain=/usr/local/gcc-10.2.0
我在在线编译器浏览器中遇到了类似的错误。
如果我通过初始化列表显式构造一个 S(这很可能会破坏就地构造的目的)std::construct_at(s, S{42, 43});
然后程序编译但链接失败。
这种做法是不是暂时违背了construct_at的目的?
如果我加上 std::move 会怎样? std::construct_at(s, std::move(S{42, 43}));
在线编译器浏览器似乎表明移动需要更多的汇编,没有它可能有一个省略(我通过添加移动创建了一个悲观主义)?
链接错误为:
/usr/bin/ld: /tmp/test-b07239.o: in function `std::__1::__throw_length_error(char const*)':
test.cpp:(.text._ZNSt3__120__throw_length_errorEPKc[_ZNSt3__120__throw_length_errorEPKc]+0x12): undefined reference to `__cxa_allocate_exception'
/usr/bin/ld: test.cpp:(.text._ZNSt3__120__throw_length_errorEPKc[_ZNSt3__120__throw_length_errorEPKc]+0x30): undefined reference to `typeinfo for std::length_error'
/usr/bin/ld: test.cpp:(.text._ZNSt3__120__throw_length_errorEPKc[_ZNSt3__120__throw_length_errorEPKc]+0x3a): undefined reference to `std::length_error::~length_error()'
显然 -stdlib=libc++
should be used linked with an ABI: -lstdc++
解决了链接错误,而 -lc++abi
仍然遗漏:
/usr/bin/ld: /tmp/test-bb0950.o: in function `std::length_error::length_error(char const*)':
test.cpp:(.text._ZNSt12length_errorC2EPKc[_ZNSt12length_errorC2EPKc]+0x23): undefined reference to `std::logic_error::logic_error(char const*)'
难道我还缺少 logic_error 的另一个库?
回到手头的关键问题:
- Clang 是否支持
std::construct_at(s, 42, 43);
?
- 使用初始化列表构造是否会影响性能? With/o搬家?
这与construct_at
无关。 S
是一个集合;除了默认构造函数和 copy/move 构造函数外,它没有可调用的构造函数。所以S
只能通过聚合初始化用值构造。
这通常需要 braced-init-list(例如:S{3, 5}
)。但是 C++20 包含一个允许聚合初始化通过构造函数语法(例如:S(3, 5)
)工作的特性,只要参数不会调用默认或 copy/move 构造函数(在这种情况下,它我会打电话给他们中的一个)。
但是铿锵doesn't implement that feature as of yet。所以 construct_at
无法构造聚合。
我正在使用最近批准的 C++20 标准功能 std::construct_at()
并试图更加熟悉它们...
我已经基于 example from CppReference.com:
构建了一个示例#include <memory>
struct S {
int a;
int b;
};
int main() {
std::allocator<S> alloc;
S * s = alloc.allocate(1);
std::construct_at(s, 42, 43); // GCC 10.2 OK Clang 12 NOT
std::destroy_at(s);
alloc.deallocate(s, 1);
s = nullptr;
}
上面的代码可以在最新的稳定版 GCC 中正常构建:
gcc-10.2 test.cpp -std=c++2a -lstdc++
但我无法使用 Clang 12 (trunk) 或 10 (stable) 对其进行编译。
clang-12 test.cpp -std=c++20 -stdlib=libc++
错误:
test.cpp:11:5: error: no matching function for call to 'construct_at'
std::construct_at(s, 42, 43); // GCC 10.2 OK Clang 12 NOT
^~~~~~~~~~~~~~~~~
/usr/local/clang/bin/../include/c++/v1/memory:903:16: note: candidate template ignored: substitution failure [with _Tp = S, _Args = <int, int>]: no matching constructor for initialization of 'S'
constexpr _Tp* construct_at(_Tp* __location, _Args&& ...__args) {
^
1 error generated.
我是不是参数包用错了?
Clang C++20 feature list 好像没说支持?
我在 Clang 中尝试使用 GCC 工具链,结果相同:--gcc-toolchain=/usr/local/gcc-10.2.0
我在在线编译器浏览器中遇到了类似的错误。
如果我通过初始化列表显式构造一个 S(这很可能会破坏就地构造的目的)std::construct_at(s, S{42, 43});
然后程序编译但链接失败。
这种做法是不是暂时违背了construct_at的目的?
如果我加上 std::move 会怎样? std::construct_at(s, std::move(S{42, 43}));
在线编译器浏览器似乎表明移动需要更多的汇编,没有它可能有一个省略(我通过添加移动创建了一个悲观主义)?
链接错误为:
/usr/bin/ld: /tmp/test-b07239.o: in function `std::__1::__throw_length_error(char const*)':
test.cpp:(.text._ZNSt3__120__throw_length_errorEPKc[_ZNSt3__120__throw_length_errorEPKc]+0x12): undefined reference to `__cxa_allocate_exception'
/usr/bin/ld: test.cpp:(.text._ZNSt3__120__throw_length_errorEPKc[_ZNSt3__120__throw_length_errorEPKc]+0x30): undefined reference to `typeinfo for std::length_error'
/usr/bin/ld: test.cpp:(.text._ZNSt3__120__throw_length_errorEPKc[_ZNSt3__120__throw_length_errorEPKc]+0x3a): undefined reference to `std::length_error::~length_error()'
显然 -stdlib=libc++
should be used linked with an ABI: -lstdc++
解决了链接错误,而 -lc++abi
仍然遗漏:
/usr/bin/ld: /tmp/test-bb0950.o: in function `std::length_error::length_error(char const*)':
test.cpp:(.text._ZNSt12length_errorC2EPKc[_ZNSt12length_errorC2EPKc]+0x23): undefined reference to `std::logic_error::logic_error(char const*)'
难道我还缺少 logic_error 的另一个库?
回到手头的关键问题:
- Clang 是否支持
std::construct_at(s, 42, 43);
? - 使用初始化列表构造是否会影响性能? With/o搬家?
这与construct_at
无关。 S
是一个集合;除了默认构造函数和 copy/move 构造函数外,它没有可调用的构造函数。所以S
只能通过聚合初始化用值构造。
这通常需要 braced-init-list(例如:S{3, 5}
)。但是 C++20 包含一个允许聚合初始化通过构造函数语法(例如:S(3, 5)
)工作的特性,只要参数不会调用默认或 copy/move 构造函数(在这种情况下,它我会打电话给他们中的一个)。
但是铿锵doesn't implement that feature as of yet。所以 construct_at
无法构造聚合。