[英]Is a defaulted constructor/assignment noexcept/constexpr by default?
[英]Defaulted move assignment cannot be explicitly noexcept if a member has a non-trivial noexcept assignment operator
此代碼無法使用gcc 4.8.2(-std = c ++ 11)進行編譯,但可以使用clang 3.4(trunk)(-std = c ++ 11)進行編譯:
#include <type_traits>
#include <vector>
struct X {
X& operator=(X&&) noexcept = default;
// adding noexcept this leads to an error in gcc, but works in clang:
// function ‘X& X::operator=(X&&)’ defaulted on its first
// declaration with an exception-specification that differs from the
// implicit declaration ‘X& X::operator=(X&&)’
std::vector<char> m;
};
// this assert holds, even without noexcept
static_assert(std::is_nothrow_move_assignable<X>::value,
"type-specification violation");
int main()
{
return 0;
}
static_assert
是gcc上有趣的部分:默認的移動分配將為noexcept
,但是我不能以這種方式聲明它。
不涉及vector
的變體是:
template<bool b>
struct F {
F& operator=(F&&) noexcept(b) {return *this;}
};
struct X {
X& operator=(X&&) noexcept = default;
F<true> f;
};
這里的預期行為是什么? 憑直覺,lang似乎是正確的。
不涉及vector
的示例應進行編譯。 叮當聲是正確的。
涉及vector
的示例可能會編譯,也可能不會編譯,具體取決於std :: lib供應商是否已將vector
的移動分配運算符標記為noexcept
。 該標准不要求此簽名為noexcept
。 如果該功能永遠不會拋出,該標准確實允許供應商添加noexcept
。
如果allocator_traits<allocator_type>::propagate_on_container_move_assignment::value
為true且is_nothrow_move_assignable<allocator_type>::value
為true(作為擴展),則libc ++將vector
移動分配運算符標記為noexcept
。 兩者在std::allocator<T>
的libc ++實現中都是正確的。
更新資料
根據要求拉開語言律師的帽子。
<disclaimer>
我正在研究不是我專長的標准的一半。
</disclaimer>
您能否更清楚地說明為什么要編譯該示例?
所有引用均來自最新的C ++ 1y工作草案N3797 。
這指定在明確默認的特殊成員上允許使用異常規范:
8.4.2 顯式默認函數 [dcl.fct.def.default] / p2
2一個明確,違約函數可以聲明
constexpr
只有它會被隱式地宣布constexpr
,並可能有一個明確的異常規范 ,只有當它是兼容的(15.4)與隱式聲明的異常規范 。
這定義了“兼容的異常規范:”
15.4 異常規格 [except.spec] / p3
3在以下情況下,兩個異常規范 兼容 :
不論其形式如何,兩者均不可投擲(見下文),
兩者的格式
noexcept
( constant-expression ),並且constant-expressions是等效的,或者兩者都是具有相同的調整類型集的動態異常規范 。
項目2涵蓋了您的情況。
這解釋了為什么在示例中隱式聲明的特殊成員為noexcept
:
15.4 異常規格 [except.spec] / p14
14繼承的構造函數(12.9)和隱式聲明的特殊成員函數(第12節)具有異常規范 。 如果f是一個繼承的構造函數或隱式聲明默認構造函數,拷貝構造函數,移動構造函數,析構函數,拷貝賦值運算符,或移動賦值運算符,其隱含的異常規范指定類型-ID
T
當且僅當T
被允許f
的隱式定義直接調用的函數的異常規范 ; 如果f
直接調用的任何函數都允許所有異常,則f
允許所有異常;如果f
直接調用的每個函數不允許任何異常,則f
具有異常規范noexcept(true)
。
因為由隱式聲明的X& operator=(X&&)
調用的每個函數都不允許有異常(即F<true>
的移動賦值運算符),所以此特殊成員為noexcept(true)
。
我相信這很重要。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.