我正在研究
noexcept
说明符和 noexcept
运算符的功能。
我知道除了使用 noexcept
运算符之外,还有一些类型特征可以替代使用,例如:
- is_nothrow_constructible
- is_nothrow_default_constructible
- is_nothrow_move_constructible
- is_nothrow_copy_constructible
- is_nothrow_assignable
- is_nothrow_move_assignable
- is_nothrow_copy_assignable
- is_nothrow_destructible
例如,在
is_nothrow_assignable
和 is_nothrow_constructible
的情况下。
struct A { };
struct B {
B& operator= (const A&) noexcept {return *this;}
B& operator= (const B&) {return *this;}
};
int main() {
std::cout << std::boolalpha;
std::cout << "is_nothrow_assignable:" << std::endl;
std::cout << "A=A: " << std::is_nothrow_assignable<A,A>::value << std::endl;
std::cout << "B=A: " << std::is_nothrow_assignable<B,A>::value << std::endl;
std::cout << "B=B: " << std::is_nothrow_assignable<B,B>::value << std::endl;
return 0;
}
在上面的代码中,很明显它测试一种类型是否可以像
std::is_nothrow_assignable<B, A>
那样不可抛出分配。
但是,我在 C++ 标准库的一些模板中看到它们使用
const
和/或 &/&&
传递参数,而其他一些模板则不使用它,类似于 std::exchange
的定义:
_EXPORT_STD template <class _Ty, class _Other = _Ty>
_CONSTEXPR20 _Ty exchange(_Ty& _Val, _Other&& _New_val) noexcept(
conjunction_v<is_nothrow_move_constructible<_Ty>, is_nothrow_assignable<_Ty&, _Other>>) { // HERE
// assign _New_val to _Val, return previous _Val
_Ty _Old_val = static_cast<_Ty&&>(_Val);
_Val = static_cast<_Other&&>(_New_val);
return _Old_val;
}
std::exchange
的参数类型为:_Ty&, _Other&&
。
在函数的第三行中使用
is_nothrow_assignable
为:
is_nothrow_assignable<_Ty&, _Other>
// ^ ^
// | |
// Here is passing as reference |
// But not here
在其他函数中也有类似的东西:
//const& ----------------
// | |
pair(const T1& x, const T2& y) noexcept(
is_nothrow_constructible<T1, const T1&>::value &&
is_nothrow_constructible<T2, const T2&>::value );
// ^ ^ ^
// | | |
// Here without const or & ------ | |
// | |
// But here is with const and & -------------
我的问题是为什么他们在某些论点中使用
const
和/或 &/&&
而在其他论点中则不使用?
我如何确定何时/何地使用它们?
is_nothrow_assignable<T, U>
告诉你,鉴于
T&& f();
U&& g();
f() = g()
是否有效且不抛出。
由于参考折叠,当
T
是参考时,T&&
与T
相同。否则,如您所料,T&&
是“对 T
的右值引用”。
因此,对于某些对象类型
A
、B
、
is_nothrow_assignable<A, B>
告诉您是否可以从 A
类型的 rvalue分配
B
类型的 rvalue,而不会引发异常。这一点也不有趣,因为你很少需要分配给右值。
is_nothrow_assignable<A&&, B&&>
相当于 is_nothrow_assignable<A, B>
。is_nothrow_assignable<A&, const B&>
告诉您是否可以从 A
类型的 const lvalue分配
B
类型的 lvalue,而不会引发异常。
is_nothrow_assignable<A&, B>
告诉您是否可以从 A
类型的 rvalue分配
B
类型的 lvalue,而不会引发异常。
is_nothrow_assignable<A&, B&&>
相当于 is_nothrow_assignable<A&, B>
。