15

这段代码发生了什么?太混乱了。

#include <utility>

struct check
{
   template <typename T>
   auto foo() -> decltype(std::declval<T>().value, void())
   {
      static_assert(T{}.value == 10, "Incorrect value");
   }
} var;

int main()
{
   struct apple
   {
      int value{10};
   };

   var.foo<apple>();
}

特别是它拥有的部分->以及之后的所有内容。

4

1 回答 1

10

让我们一点一点来。

auto foo() -> decltype(std::declval<T>().value, void())

这是一个尾随返回类型。允许使用参数,但在这里不是必须的。我想它是这样写的更清楚。decltype查找内部表达式的类型,但实际上并未计算该表达式。std::declval用于创建传递给它的类型的实例。逗号运算符在这里用于生成整体返回类型void,因为逗号运算符计算左侧,将其丢弃,计算右侧,然后返回。

第一部分创建了一种 SFINAE(尽管我从未见过这样使用它)。例如,如果您有一个重载foothat 用value2而不是做同样的事情value,那么调用哪个就没有歧义了。请参阅此处了解我的意思。将它与这个比较,它只有一个返回类型void并导致错误。

static_assert(T{}.value == 10, "Incorrect value");

此行确保Tvalue成员的值初始化实例的值为 10。如果不是,则生成带有该文本的编译器错误。

} var;

这只是要使用的该类的全局对象。

struct apple
{
   int value{10};
};

这是一个用于测试它的示例类。它有一个value成员,并且该成员在值初始化实例中为 10(默认初始化也是如此)。

var.foo<apple>();

这只是调用函数。

于 2013-05-26T18:29:10.303 回答