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
+ {{ 1}} - &gt; &&
,这是一个无法分配的左值。)
为什么int&&
以这种方式设计,或者我误解了std::is_assignable
真正含义的内容?
相关讨论:
答案 0 :(得分:19)
在这些特征中,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
。分配给rvalues是有用的,甚至是常见的,尽管在绝大多数赋值用途中都没有这样做。
因此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
。只有当这些特征不适合您时(可能因为您需要查看异构分配),您是否应该直接使用vector<bool>::reference
。然后,您需要处理是否要在lhs上允许rvalues的问题,以便考虑可能涉及tuple
或#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");
}
引用的案例。您必须明确选择是否要在is_assignable查询中允许此类情况。
例如:
{{1}}
答案 1 :(得分:6)
std::is_assignable<int, int>::value == false
表示“无法将int
字面值分配给int
字面值”(等等)。
您的陈述int x = 3
为std::is_assignable<int&, int>::value
。
欲了解更多信息: http://en.cppreference.com/w/cpp/types/is_assignable
答案 2 :(得分:0)
一个务实的答案是,您可以通过修改左参数来获得通常想要的东西。
查询std::is_assignable_t<T&,U>
将告诉您是否可以合理地编写代码,例如:
T t;
U u;
t = u;
我说这很实用,因为如果他们写了std::is_assignable<>
以在左侧使用内置的左值引用,则要重用此替代方案以获取其当前功能会更加困难。如果用户在外部向任意类型添加左值引用(不会被删除),比在外部为不同查询(可以轻松删除)要求右值引用要简单。
因此,此版本的std::is_assignable<>
将回答您典型的“从右值接收左值”赋值测试,但也会回答更罕见的查询。
这种灵活性的代价是您所描述的违反直觉的本质。