为什么std :: is_assignable反直觉?

时间:2013-11-12 03:14:43

标签: c++ c++11 typetraits

符合实现的

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真正含义的内容?

相关讨论:

3 个答案:

答案 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 = 3std::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<>将回答您典型的“从右值接收左值”赋值测试,但也会回答更罕见的查询。

这种灵活性的代价是您所描述的违反直觉的本质。