我正在尝试使用最近批准的C++20标准特性std::construct_at()
,并试图更加熟悉它们...
我基于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 功能列表似乎尚未支持? 我已经尝试使用GCC工具链在Clang中进行编译,结果相同:
--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++
应该与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*)'
我是否还缺少逻辑错误的另一个库?
回到关键问题:
- Clang是否支持
std::construct_at(s, 42, 43);
? - 使用初始化列表构造会有性能损失吗?带/不带移动操作?
clang++
12(我自己只有9),如果您尝试使用语言中的_HEAD_功能,将会发生变化。 - Ted Lyngmo