12

std::is_assignable<int, int>::value == false在符合标准的实现中(例如 clang/libc++、gcc/libstdc++,但不是 VS2012)。

直观地说,这意味着诸如此类的表达式int x = 3;是无效的。但是is_assignable赋值双方都转换为 的状态规范std::add_rvalue_reference<T>::type,因此std::is_assignable<int, int>::value必须评估为false(因为int+ &&-> int&&,这是一个不可赋值的右值)。

为什么要std::is_assignable这样设计,还是我误解了is_assignable<int, int>::value真正的含义?

相关讨论:

4

3 回答 3

22

在这些特征中,并且T不是左值引用类型,T意味着右值。

对于许多用户定义的类型T,分配给右值类型是完全合理的。它在某些情况下甚至非常有用:

std::vector<bool> v(5);
v[0] = true;

在上面的表达式中,v[0]是一个被分配到的右值。如果vector<bool>是一个糟糕的例子,那么下面的新 C++11 代码也会做同样的事情:

#include <tuple>

std::tuple<int, int>
do_something();

int
main()
{
    int i, j;
    std::tie(i, j) = do_something();
}

上面, 的结果do_something()被分配给一个 rvalue std::tuple。赋值给右值很有用,甚至很常见,尽管在大多数赋值用法中都没有这样做。

因此std::is_assignable允许确定能够分配给右值和左值之间的区别。如果您需要知道区别,std::is_assignable可以为您完成工作。

如果您正在处理更常见的情况,例如只是想弄清楚一个类型T是否可以复制分配,那么使用is_copy_assignable<T>. 这个特性是根据字面定义的,is_assignable并强制 lhs 为左值:

is_copy_assignable<T> == is_assignable<T&, const T&>

正如预期的那样,这std::is_copy_assignable<int>::value将是真的。

is_copy_assignable用作您的首选,或者如果is_move_assignable您也需要。只有当这些特征对您不起作用时(可能是因为您需要查看异构分配),您才应该恢复is_assignable直接使用。然后您需要处理是否要在 lhs 上允许右值的问题,以便考虑可能涉及 avector<bool>::reference或 atuple引用的情况。您必须明确选择是否要在 is_assignable 查询中允许此类情况。

例如:

#include <type_traits>
#include <vector>

int
main()
{
    static_assert(std::is_assignable<std::vector<bool>::reference&, bool>(),
        "Should be able to assign a bool to an lvalue vector<bool>::reference");

    static_assert(std::is_assignable<std::vector<bool>::reference, bool>(),
        "Should be able to assign a bool to an rvalue vector<bool>::reference");

    static_assert(std::is_assignable<bool&, std::vector<bool>::reference>(),
        "Should be able to assign a vector<bool>::reference to an lvalue bool");

    static_assert(!std::is_assignable<bool, std::vector<bool>::reference>(),
        "Should not be able to assign a vector<bool>::reference to an rvalue bool");
}
于 2013-11-12T04:44:20.927 回答
7

std::is_assignable<int, int>::value == false意味着“int不能将文字分配给int文字”(除其他外)。

你的说法int x = 3std::is_assignable<int&, int>::value

欲了解更多信息: http ://en.cppreference.com/w/cpp/types/is_assignable

于 2013-11-12T13:07:20.380 回答
0

一个务实的答案是,你可以通过修改左参数来得到你通常想要的东西。

该查询std::is_assignable_t<T&,U>将告诉您是否可以合理编写代码,例如:

T t;
U u;
t = u;

我说这是务实的,因为如果他们在左侧编写std::is_assignable<>使用内置左值引用,那么重用这个替代方案来获得其当前功能会更加困难。如果用户在外部添加一个对任意类型的左值引用(它不会被擦除),这比在外部需要一个右值引用来进行不同的查询(很容易被擦除)更简单。

因此,此版本std::is_assignable<>将回答您典型的“从右值接收左值”分配测试,但也会回答更罕见的查询。

这种灵活性的惩罚是您描述的违反直觉的性质。

于 2019-09-23T19:57:07.193 回答