带有两个参数的decltype是什么?

编辑,以避免混淆:decltype不接受两个参数。 查看答案。

以下两个结构可用于在编译时检查decltype类型上是否存在成员函数:

// 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,因此,如果decltype无效,则仅定义bar的椭圆形式,该椭圆形式返回T。 否则,第一种方法是为T定义的,并且将返回bar(*p)。实际的“开关”发生在第二个类中,该类继承自p返回的类型。与使用T*和类似方法的不同方法相比,这似乎很聪明和“轻巧”。 。

带有两个参数的decltype首先让我感到惊讶,因为我认为它只是一种表达式的类型。 当我看到上面的代码时,我认为这就像“尝试编译表达式并始终返回第二个表达式的类型。如果表达式无法编译则失败”(因此请隐藏此专业知识; SFINAE)。

但:

然后,我认为我可以使用此方法编写任何“有效表达式”检查器,只要它取决于某种类型decltype

...
    template<class T>
    static auto test(T* p) -> decltype(bar(*p), std::true_type());
...

[HTTP://IDE one.com/DJ KL PF]

因此,我认为,仅当定义bar并接受T作为第一个参数(或T可转换等)时,才会返回decltype,即:如果在某些情况下编写了bar(*p) 其中p定义为T*类型。

但是,上面的修改始终评估为decltype。这是为什么? 我不想用一些复杂的不同代码来修复它。 我只想知道为什么它不按我预期的那样工作。 显然,带有两个参数的decltype的工作方式与我想象的不同。 我找不到任何文档。 到处都只有一个表达式来解释。

leemes asked 2020-07-31T03:24:13Z
2个解决方案
37 votes

这是一个用逗号分隔的表达式列表,其类型与列表中最后一个表达式的类型相同。 通常用于验证第一个表达式是否有效(可编译,以为SFINAE),第二个用于指定decltype在第一个表达式有效的情况下应返回。

Daniel Frey answered 2020-07-31T03:24:31Z
14 votes

decltype不接受两个参数。 简单来说,它可以将表达式作为其参数,而逗号运算符是创建表达式的一种方式。 根据第5.18 / 1段:

[...]用逗号分隔的一对表达式从左到右求值; 左边的表达式是一个废弃值 表达式(第5条)。 与左表达式相关的每个值计算和副作用 在与正确的表达式相关联的每次值计算和副作用之前进行排序。 方式 结果的值是右操作数的类型和值; 结果属于相同的值类别 作为其右操作数,如果其右操作数是glvalue和位字段,则为位字段。 如果值合适 操作数是一个临时值(12.2),结果是该临时值。

因此:

static_assert(std::is_same<decltype(42, 3.14), double>::value, "Will not fire");
Andy Prowl answered 2020-07-31T03:25:01Z
translate from https://stackoverflow.com:/questions/16044514/what-is-decltype-with-two-arguments