如果可能,隐式移动构造函数应为 noexcept
Implicit move constructor shall be noexcept if possible
基本符合标准:
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-id T
if and only if T
is allowed by the exception-specification
of a function directly invoked by f
’s implicit definition; f
allows all exceptions if any function it directly invokes allows all exceptions, and f
has the exception-specification noexcept(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?
是的。 const
成员Foo::stringField
不是std::string
,而是const std::string
。 const std::string
不是可构造的 1,因此 Foo
的隐式移动构造函数也不是。
1 Const 右值不能绑定到非const 右值引用,因此不会使用移动构造函数。相反,使用复制构造函数并且 std::string
的复制构造函数可能会抛出。
基本符合标准:
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?
是的。 const
成员Foo::stringField
不是std::string
,而是const std::string
。 const std::string
不是可构造的 1,因此 Foo
的隐式移动构造函数也不是。
1 Const 右值不能绑定到非const 右值引用,因此不会使用移动构造函数。相反,使用复制构造函数并且 std::string
的复制构造函数可能会抛出。