【问题标题】:std::is_assignable and std::pair<const T, U>std::is_assignable 和 std::pair<const T, U>
【发布时间】:2017-11-16 06:14:24
【问题描述】:

不出所料,下面的代码does not compile

#include <type_traits>
#include <utility>
int main()
{
    using T = std::pair<const int, int>;
    const auto ok = std::is_assignable<T, T>::value; // true
    T x;
    T y;
    x = y; // compiler error
}

但是okis true的值用下面三个编译器。

  • g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
  • clang 版本 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
  • MSVC++ 2017 15.2 26430.6

这是为什么?

【问题讨论】:

  • 你能尝试用一个系统来编译它,给你实际的错误信息,然后给我们看吗?
  • 你是如何准确推断出它是真的? OK 上的静态断言失败。 coliru.stacked-crooked.com/a/aba0debbfc609c11
  • std::cout &lt;&lt; std::boolalpha &lt;&lt; ok &lt;&lt; '\n'; 使用 Clang 5.0 输出 false
  • ok 适用于 gcc
  • godbolt.org/g/cMfcBP 正如霍尔特所说,gcc

标签: c++ c++11


【解决方案1】:
  1. is_assignable 提出的问题是“是否存在接受这些参数的赋值运算符签名”,而不是“该赋值运算符是否会真正编译”(在标准术语中,它只考虑赋值表达式):

    template<class T>
    struct foo {
        T t {};
        foo& operator=(const foo& r) { t = r.t; };
    };
    static_assert(std::is_copy_assignable<foo<const int>>::value, ""); // OK
    
    void bar() {
        foo<const int> f1, f2;
        f1 = f2; // explodes
    }
    
  2. pair 的赋值运算符不能默认,因为当对包含引用时它需要做一些特殊的事情。这意味着需要采取额外的预防措施来确保is_assignable 不会说谎(例如,如果成员类型不可复制分配,请确保删除复制分配运算符)。直到very recently,该标准才强制要求采取此类预防措施。

  3. is_assignable&lt;T, T&gt; 询问是否可以将 T 右值分配给 T 右值。这是一个奇怪的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    • 2023-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多