jjzjj

c++ - 对于具有抛出复制构造函数和 noexcept 按值复制赋值的类,is_nothrow_copy_assignable 的值是多少?

coder 2024-02-10 原文

根据 C++ 标准,以下程序的预期(如果有)输出是什么:

#include <iostream>
#include <iomanip>
#include <type_traits>

class A {
public:
    A() = default;
    ~A() = default;
    A(A const& other) {}
    A(A&& other) noexcept {}
    A& operator=(A other) noexcept { return *this; }
};

int main() {
    std::cout << std::boolalpha
        << std::is_nothrow_copy_assignable<A>::value << "\n"
        << std::is_nothrow_move_assignable<A>::value << "\n";
}

换句话说,类型特征值的评估是否只看赋值运算符的声明,即 noexcept,并因此产生

true
true

或者它是否考虑调用上下文( abA 的实例)

a = b;            // may throw, implicitly calls copy c'tor
a = std::move(b); // noexcept, implicitly calls move c'tor

它是否产生

false
true

实践尝试

使用 Visual Studio 2015 运行代码,Update 3 提供

true
true

而 gcc 6.1 给出了

false
true

谁是对的?

背景

当我们有一个带有抛出复制构造函数(因为资源分配可能会失败)、一个 noexcept 移动构造函数、一个抛出复制赋值和一个 noexcept 移动赋值的资源管理类时,就会出现这种情况。

假设复制和移动分配都可以根据交换 IDOM 有效地实现:

A& operator=(A const& other) {
    A(other).swap(*this); // calls the copy c'tor, may throw
    return *this;
}

A& operator=(A&& other) noexcept {
    A(std::move(other)).swap(*this); // calls noexcept move c'tor
    return *this;
}

然后我们可能会考虑将两者压缩成单个按值复制分配

A& operator=(A other) noexcept {
    other.swap(*this);
    return *this;
}

但是,我们只有在 std::is_nothrow_copy_assignable<A> 时才能安全地执行此操作和 std::is_nothrow_move_assignable<A>提供正确的值(分别为 false 和 true)。否则,依赖于这些类型特征的代码会表现得很糟糕,我们的单个按值赋值将不能正确地替代两个单独的赋值运算符。

最佳答案

is_nothrow_copy_assignable的定义在 [meta.unary.prop] 中:

For a referenceable type T, the same result as is_nothrow_assignable_v<T&, const T&>, otherwise false.

好的,A是可引用的(意思是 A& 是有效的)。所以我们进入is_nothrow_assignable :

is_assignable_v<T, U> is true and the assignment is known not to throw any exceptions (5.3.7).

is_assignable_v<A, A const&>绝对是true , 所以我们满足第一部分。众所周知不抛出任何异常是什么意思?根据 [expr.unary.noexcept]:

The noexcept operator determines whether the evaluation of its operand, which is an unevaluated operand (Clause 5), can throw an exception (15.1). [...] The result of the noexcept operator is true if the set of potential exceptions of the expression (15.4) is empty, and false otherwise.

在 [except.spec] 中:

The exception-specification noexcept or noexcept(constant-expression), where the constant-expression yields true, denotes an exception specification that is the empty set. The exception-specification noexcept(constant-expression), where the constant-expression yields false, or the absence of an exception-specification in a function declarator other than that for a destructor (12.4) or a deallocation function (3.7.4.2) denotes an exception specification that is the set of all types.

和:

The set of potential exceptions of an expression e is empty if e is a core constant expression (5.20). Otherwise, it is the union of the sets of potential exceptions of the immediate sub-expressions of e, including default argument expressions used in a function call, combined with a set S defined by the form of e, as follows: [...]
— If e implicitly invokes one or more functions (such as an overloaded operator, an allocation function in a new-expression, or a destructor if e is a full-expression (1.9)), S is the union of:
   — the sets of types in the exception specifications of all such functions, and
   — if e is a new-expression [...]

现在,一个 A 的赋值来自 A const&包括两个步骤:

  1. 调用A的拷贝构造函数
  2. 调用A 的复制赋值运算符|

异常规范是这两个函数的所有异常规范的 union ,它是所有类型的集合——因为复制构造函数根本没有异常规范

因此,is_nothrow_copy_assignable_v<A>应该是 false . gcc 是正确的。

关于c++ - 对于具有抛出复制构造函数和 noexcept 按值复制赋值的类,is_nothrow_copy_assignable 的值是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42034848/

有关c++ - 对于具有抛出复制构造函数和 noexcept 按值复制赋值的类,is_nothrow_copy_assignable 的值是多少?的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  3. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  4. ruby - 怎么来的(a_method || :other) returns :other only when assigning to a var called a_method? - 2

    给定以下方法:defsome_method:valueend以下语句按我的预期工作:some_method||:other#=>:valuex=some_method||:other#=>:value但是下面语句的行为让我感到困惑:some_method=some_method||:other#=>:other它按预期创建了一个名为some_method的局部变量,随后对some_method的调用返回该局部变量的值。但为什么它分配:other而不是:value呢?我知道这可能不是一件明智的事情,并且可以看出它可能有多么模棱两可,但我认为应该在考虑作业之前评估作业的右侧...我已经在R

  5. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  6. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  7. ruby - 导轨 4 : column reference "updated_at" is ambiguous with Postgres - 2

    我正在尝试使用“updated_at”字段的日期时间范围查询数据库。前端在JSON数组中发送查询:["2015-09-0100:00:00","2015-10-0223:00:00"]在RailsController中,我使用以下方法将两个字符串解析为DateTime:start_date=DateTime.parse(params[:date_range_arr][0])end_date=DateTime.parse(params[:date_range_arr][1])#...@events=@events.where('updated_atBETWEEN?AND?,start_d

  8. ruby-on-rails - "assigns"在 Ruby on Rails 中有什么作用? - 2

    我目前正在尝试学习RubyonRails和测试框架RSpec。assigns在此RSpec测试中做什么?describe"GETindex"doit"assignsallmymodelas@mymodel"domymodel=Factory(:mymodel)get:indexassigns(:mymodels).shouldeq([mymodel])endend 最佳答案 assigns只是检查您在Controller中设置的实例变量的值。这里检查@mymodels。 关于ruby-o

  9. ruby - what is - gets is a directory - 错误信息 - 2

    我遇到了这个奇怪的错误.../Users/gideon/Documents/ca_ruby/rubytactoe/lib/player.rb:13:in`gets':Isadirectory-spec(Errno::EISDIR)player_spec.rb:require_relative'../spec_helper'#theuniverseisvastandinfinite...itcontainsagame....butnoplayersdescribe"tictactoegame"docontext"theplayerclass"doit"musthaveahumanplay

  10. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

随机推荐