有两个参数的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_typetest的椭圆版本。 否则,第一个方法被定义为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");