clang ++ 12是否支持C ++ 20 std :: construct_at?

时间:2020-09-26 04:01:55

标签: c++ clang++ c++20

我正在使用最近批准的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

我在在线编译器浏览器中也遇到了类似的问题。

如果我通过initializer-list显式构造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);吗?
  • 使用初始化列表结构是否会对性能产生影响?有/没有移动?

1 个答案:

答案 0 :(得分:6)

这与construct_at无关。 S是一个汇总;除了默认构造函数和复制/移动构造函数之外,没有其他可调用的构造函数。因此S只能通过聚合初始化用值构造。

这通常需要一个括号初始化列表(例如:S{3, 5})。但是C ++ 20包含一项功能,该功能允许聚合初始化通过构造函数语法(例如:S(3, 5))工作,只要参数不会调用默认构造函数或复制/移动构造函数(在这种情况下,它将打电话给他们之一)。

但是C doesn't implement that feature as of yet。因此construct_at无法构造聚合。