gpt4 book ai didi

c++ - 如果成员具有非平凡的 noexcept 赋值运算符,则默认 move 赋值不能显式地为 noexcept

转载 作者:IT老高 更新时间:2023-10-28 22:41:37 27 4
gpt4 key购买 nike

此代码使用 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 中有趣的部分:默认的 move 分配将是 noexcept,但我不能这样声明。

不涉及vector的变体是:

template<bool b>
struct F {
F& operator=(F&&) noexcept(b) {return *this;}
};

struct X {
X& operator=(X&&) noexcept = default;
F<true> f;
};

这里的预期行为是什么?直觉上,clang 似乎是正确的。

最佳答案

示例不涉及 vector应该编译。 clang 在这一点上是正确的。

涉及 vector 的示例可能编译也可能不编译,取决于 std::lib 供应商是否标记了 vector 的 move 赋值运算符作为 noexcept或不。该标准不要求此签名为 noexcept .该标准允许供应商添加 noexcept如果函数永远不会抛出。

libc++标记vector将赋值运算符 move 为 noexcept如果 allocator_traits<allocator_type>::propagate_on_container_move_assignment::value是真的,is_nothrow_move_assignable<allocator_type>::value是真的(作为符合标准的扩展)。这两种情况在 std::allocator<T> 的 libc++ 实现中都是正确的。 .

更新

应要求摘下语言律师帽。

<disclaimer>

我正在研究不属于我专业领域的一半标准。

</disclaimer>

Could you be more explicit on why the example should compile?

所有引用均来自最新的 C++1y 工作草案 N3797 .


这指定允许在显式默认的特殊成员上使用异常规范:

8.4.2 显式默认函数 [dcl.fct.def.default]/p2

2 An explicitly-defaulted function may be declared constexpr only if it would have been implicitly declared as constexpr, and may have an explicit exception-specification only if it is compatible (15.4) with the exception-specification on the implicit declaration.


这定义了“兼容的异常规范:”

15.4 异常规范 [except.spec]/p3

3 Two exception-specifications are compatible if:

  • both are non-throwing (see below), regardless of their form,

  • both have the form noexcept(constant-expression) and the constant-expressions are equivalent, or

  • both are dynamic-exception-specifications that have the same set of adjusted types.

Bullet 2 涵盖了您的情况。


这解释了为什么隐式声明的特殊成员是 noexcept在你的例子中:

15.4 异常规范 [except.spec]/p14

14 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.

因为每个函数都由隐式声明的 X& operator=(X&&) 调用不允许异常(exception)(即 F<true> 的 move 赋值运算符),此特殊成员是 noexcept(true) .


相信这已经确定了。

关于c++ - 如果成员具有非平凡的 noexcept 赋值运算符,则默认 move 赋值不能显式地为 noexcept,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20610658/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com