在测试const对象成员的处理时,我在 clang 中遇到了这个明显的错误。该代码可在 msvc 和 gcc 中运行。然而,该错误仅出现在非常量中,这无疑是最常见的用途。我做错了什么还是这是一个真正的错误?
https://godbolt.org/z/Gbxjo19Ez
#include <string>
#include <memory>
struct A
{
// const std::string s; // Oddly, declaring s const compiles
std::string s;
constexpr A() = default;
constexpr A(A&& rh) = default;
constexpr A& operator=(A&& rh) noexcept
{
std::destroy_at(this);
std::construct_at(this, std::move(rh));
return *this;
}
};
constexpr int foo()
{
A i0{}; // call ctor
// Fails with clang. OK msvc, gcc
// construction of subobject of member '_M_local_buf' of union with no active member is not allowed in a constant expression { return ::new((void*)__location) _Tp(std::forward<_Args>(__args)...); }
i0 = A{}; // call assign rctor
return 42;
}
int main() {
constexpr int i = foo();
return i;
}
Run Code Online (Sandbox Code Playgroud)
对于那些感兴趣的人,这是将 const 对象转换为一等公民的完整版本(可用于向量、排序等)。我真的不喜欢添加吸气剂来保持不变性。
是的,这是一个 libstdc++ 或 clang 问题:std::string的移动构造函数不能在常量表达式中使用。下面给出了同样的错误:
#include <string>
constexpr int f() {
std::string a;
std::string b(std::move(a));
return 42;
}
static_assert(f() == 42);
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/3xWxYW717
https://en.cppreference.com/w/cpp/compiler_support尚未显示 clang 支持 constexpr std::string。