簡體   English   中英

如果成員具有非平凡的noexcept賦值運算符,則默認的移動賦值不能明確地為noexcept

[英]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在以下情況下,兩個異常規范 兼容

  • 不論其形式如何,兩者均不可投擲(見下文),

  • 兩者的格式noexceptconstant-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM