【问题标题】:Why this inline method with deduced return type not defined yet?为什么这个带有推导返回类型的内联方法尚未定义?
【发布时间】:2017-02-19 16:27:53
【问题描述】:
#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 使其工作。

【问题讨论】:

  • 内联函数定义就像你在类定义的末尾之后写的,所以在static_assert处,函数还没有定义.
  • @KerrekSB 但将返回类型更改为显式使其编译正常
  • 当然,但auto 的全部意义在于从定义中推断出类型...
  • 当你明确返回类型时,函数的声明就足以知道返回类型。当返回类型为auto 时,编译器在声明时并不知道返回类型是什么;它必须等到函数定义,这会在稍后发生。
  • @Danra:是的。 decltype 是关于(紧紧抓住)声明的类型。但是auto 做出了依赖于定义的声明。

标签: c++ c++11 auto


【解决方案1】:

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

但是,当func 声明为返回类型占位符auto 时,func 的声明取决于它的定义,所以func 的类型,因此表达式func(),在定义函数之前是未知的。

当您在类定义中内联定义类成员函数时,就好像定义将出现在类定义的末尾之后(也就是说,函数体可能会引用词法声明的名称稍后在类定义中)。这样做的结果和 auto 的语义是,您的函数 auto func 实际上直到类定义结束才完全声明,因此 func() 的类型直到那么。

【讨论】:

  • “当您在类定义中内联定义类成员函数时,就好像该定义将出现在类定义结束之后” - 这有什么好的理由吗?
  • @Danra:用户的共同期望是能够参考班级成员?
  • 如果将内联函数“附加”到类定义中,那还不行吗?这反过来又允许使用他们推导出的返回类型。
  • @Danra:对不起,我不明白你说的和我说的有什么不同。实际上,就好像内联函数的定义被“附加”到了类定义中。
  • 我以为你的意思是函数是在类定义“过去”定义的,而不是附加到它的末尾。在那种情况下,使用推导的返回类型有什么问题?这只是班级内的顺序问题吗? (即该类型在编译器“看到”之前不能使用,这比它需要它的时间晚)
【解决方案2】:

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

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

#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';
}

【讨论】:

    猜你喜欢
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 2021-01-28
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    相关资源
    最近更新 更多