有两个参数的decltype是什么?
编辑,为了避免混淆:
decltype
不接受两个参数。 查看答案。
在编译期间,可以使用以下两个结构来检查typesT
上成员函数的存在:
// Non-templated helper struct: struct _test_has_foo { template<class T> static auto test(T* p) -> decltype(p->foo(), std::true_type()); template<class> static auto test(...) -> std::false_type; }; // Templated actual struct: template<class T> struct has_foo : decltype(_test_has_foo::test<T>(0)) {};
我认为这个想法是在检查成员函数的存在时使用SFINAE,所以在p->foo()
无效的情况下,只定义返回std::false_type
的test
的椭圆版本。 否则,第一个方法被定义为T*
,并将返回std::true_type
。 实际的“开关”发生在第二个类中,它inheritance自test
返回的types。 与is_same
等不同的方法相比,这看起来很聪明和“轻量级”。
有两个参数的decltype
首先让我感到惊讶,因为我认为它只是得到了一个expression式的types。 当我看到上面的代码时,我认为它是“试图编译expression式,并总是返回第二种types,如果expression式编译失败,则失败”(所以隐藏这个特殊化; SFINAE)。
但:
然后我想我可以用这个方法来写任何“有效的expression式”检查器,只要它依赖于某种types的T
例:
... template<class T> static auto test(T* p) -> decltype(bar(*p), std::true_type()); ...
http://ideone.com/dJkLPF
这个,所以我想,当且仅当bar
被定义接受T
作为第一个参数(或者如果T
是可转换的等等)时,才会返回一个std::true_type
,即:如果bar(*p)
会编译如果它是在某种情况下写的,那么p
就是T*
types。
但是,上面的修改始终是std::false_type
。 为什么是这样? 我不想用一些复杂的不同代码来修复它。 我只是想知道为什么它不像我预期的那样工作。 显然, 有两个论点的decltype
与我想象的不同。 我找不到任何文件; 这只是一个expression无处不在的解释。
它是逗号分隔的expression式列表,types与列表中最后一个expression式的types相同。 它通常用于validation第一个expression式是否有效(可编译,认为SFINAE),第二个用于指定在第一个expression式有效的情况下应该返回decltype
。
decltype
不需要两个参数。 简而言之,它可以有一个expression式作为它的参数,而逗号操作符是创buildexpression式的一种方式。 根据第5.18 / 1段:
[…]用逗号分隔的一对expression式从左到右计算; 左expression式是一个丢弃值expression式(第5章)。 与左expression式相关的每个值计算和副作用在与右expression式相关联的每个值计算和副作用之前被sorting。 结果的types和值是右操作数的types和值 ; 结果与右操作数具有相同的值类别,如果右操作数是一个glvalue和一个位域,则结果是一个位域。 如果右操作数的值是临时值(12.2),则结果是临时的。
因此:
static_assert(std::is_same<decltype(42, 3.14), double>::value, "Will not fire");