std :: is_assignable如何工作?

时间:2014-09-29 00:38:08

标签: c++ c++11

以下是std::is_assignable的实现,我花了几个小时试图了解如何静态地找出模板化对象的类型但不能。

在标准is_assignable状态中,分配的双方都转换为std::add_rvalue_reference<T>::type。我没有得到那个句子,也没看到std::add_rvalue_reference<T>::type如何用来预测对象的类型。

有人能够给我一个简单的解释,我可以用它来了解std :: is_assignable的工作原理吗?

1 个答案:

答案 0 :(得分:6)

这里有相同的代码,其中包含了一些词法混淆:

 1043     template <typename Tp, typename Up>
 1044     class is_assignable_helper
 1046     {
 1047       template <typename Tp1, typename Up1>
 1048         static decltype(declval<Tp1>() = declval<Up1>(), one())
 1049         test(int);
 1050 
 1051       template<typename, typename>
 1052         static two test(...);
 1053 
 1054     public:
 1055       static constexpr bool value = sizeof(test<Tp, Up>(0)) == 1;
 1056     };

本课程使用SFINAE来完成肮脏的工作。也就是说,变量value的值将取决于基于重载决策选择的test()函数。一个重载采用整数,另一个采用C variadic参数(由省略号指定)。如果在第一次重载时发生替换失败,则将选择第二次重载。

如果替换失败发生,则它将来自表达式declval<Tp1>() = declval<Up1>()declval<T>()是一个函数声明,&#34;返回&#34;类型std::add_rvalue_reference<T>::type的值。此函数主要用于未评估的上下文,如decltype()sizeof()noexcept()等,以便在不显式调用构造函数的情况下获取类型的实例(因为该类型可能没有一个可访问的构造函数)。如果您想知道为什么add_rvalue_reference是所选择的返回类型,请参阅this post

获得该类型的实例后,可以在这些实例上调用成员/非成员函数。使用的成员函数是operator=()。如果某个类没有赋值运算符(或具有不可访问的运算符),则会发生替换失败。将改为选择test()的后备(可变参数)版本。

参数类型(int vs ...)之间存在差异的原因是因为...具有最低的转换排名,并且它充当了最后的手段&#34;用于重载分辨率。我们不能将参数留空,否则我们会收到重新声明错误。

至于test的返回类型 - 如果替换失败发生(类型Up的值可以分配给类型{{1}的值然后Tp返回一个表示成功的类型。如果确实发生了替换失败,则选择返回指示失败的类型的回退版本。这些类型通过检查其大小来区分。我们通过与test()进行比较来检查是否成功。