在这些特征中,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() 的结果被分配给一个右值 std::tuple。赋值给右值很有用,甚至很常见,尽管在大多数赋值用法中都没有这样做。
所以std::is_assignable 允许确定能够分配给右值和左值之间的区别。如果您需要了解其中的区别,std::is_assignable 可以为您完成这项工作。
如果您正在处理更常见的情况,例如只是试图确定类型 T 是否可复制分配,则使用 is_copy_assignable<T>。这个 trait 按字面意思定义为 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 上允许右值的问题,以便考虑可能涉及 vector<bool>::reference 或 tuple 引用的情况。您必须明确选择是否要在 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");
}