为什么这个带有推导返回类型的内联方法尚未定义?

时间:2017-02-19 16:27:54

标签: c++ c++11 auto

#include <string>
#include <type_traits>

class C
{
    static auto func() { return std::string("hello"); }
    static_assert(std::is_same<decltype(func()), std::string>::value, "");
};

GCC和Clang都不接受这一点,说func在定义之前就已使用了。为什么呢?

将推断的auto返回类型更改为std::string使其有效。

2 个答案:

答案 0 :(得分:3)

decltype构造生成标识符或表达式的声明类型。当使用返回类型声明func时,调用表达式func()的类型是已知的,并且一切都按预期工作。

但是,当使用返回类型占位符func声明auto时,func 的声明取决于其定义,因此{的类型在定义函数之前,{1}}以及表达式func是未知的。

当你在类定义中内联定义一个类成员函数时,就好像定义是在类定义结束后出现的那样(也就是说,函数体可以引用词法声明的名称< em>稍后在类定义中)。这个的结果和func()的语义是你的函数auto实际上并没有完全声明直到类定义结束,因此{{1}的类型直到那时才能知道。

答案 1 :(得分:1)

除了其他答案之外,可能的解决方法是将检查推迟到静态函数,并依靠优化器删除所有冗余代码。

在发布版本中,这应该是零成本:

#include <string>
#include <type_traits>
#include <iostream>

struct C
{
    static auto func() {
        check_same();
        return std::string("hello");
    }

private:

    static void check_same()
    {
        static_assert(std::is_same<decltype(func()), std::string>::value, "");
    }
};

int main()
{
  std::cout << C::func() << '\n';
}