基本按标准:
An inheriting constructor (12.9) and an implicitly declared special member function (Clause 12) have an exception-specification. If
f
is an inheriting constructor or an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-idT
if and only ifT
is allowed by the exception-specification of a function directly invoked byf
’s implicit definition;f
allows all exceptions if any function it directly invokes allows all exceptions, andf
has the exception-specificationnoexcept(true)
if every function it directly invokes allows no exceptions.
因此,以下代码片段应具有隐式 noexcept 移动构造函数:
template<typename _Tp>
class Foo
{
public:
Foo() = default;
explicit Foo(const std::string& s, const std::function<bool(_Tp&)>& f) : stringField(s), funcField(f) {}
private:
const std::string stringField;
std::function<bool(_Tp&)> funcField;
};
但不幸的是,它没有:
int main()
{
std::cout << "std::string: " << std::is_nothrow_move_constructible_v<std::string> << std::endl;
std::cout << "std::function: " << std::is_nothrow_move_constructible_v<std::function<bool(std::string&)>> << std::endl;
std::cout << "string_t: " << std::is_nothrow_move_constructible_v<Foo<std::string>> << std::endl;
return 0;
}
打印
std::string: 1
std::function: 1
string_t: 0
在 Ubuntu 18.04 LTS 上使用 g++ 8.3.0
我有什么遗漏吗?
最佳答案
Is there something I am missing?
是的。 常量
成员Foo::stringField
不是std::string
,它是const std::string
。 const std::string
不是 nothrow move 构造函数1,因此 Foo
的隐式 move 构造函数也不是。
1 const rvalue 不能绑定(bind)到非 const rvalue 引用,因此将不会使用 move 构造函数。相反,使用了复制构造函数,并且 std::string
的复制构造函数可能会抛出。
关于c++ - 如果可能,隐式移动构造函数应为 noexcept,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61730423/