为什么这个推导的 return 类型的内联方法还没有定义?
Why this inline method with deduced return type not defined yet?
#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
return 类型更改为 std::string
使其工作。
decltype
构造生成标识符或表达式的声明类型。当使用 return 类型声明 func
时,调用表达式 func()
的类型是已知的并且一切都按预期工作。
然而,当func
声明为return类型占位符auto
时,那么func
的声明取决于它的定义,因此 func
的类型以及表达式 func()
的类型在定义函数之前是未知的。
当您在 class 定义中内联定义一个 class 成员函数时,就好像该定义紧跟在 class 定义的结尾(即,函数体可能会引用在 class 定义中 later 词法声明的名称)。这个结果和 auto
的语义是你的函数 auto func
实际上没有完全 声明 直到 class 定义结束,并且因此 func()
的类型直到那时才能知道。
除了其他答案之外,一个可能的解决方法是将检查推迟到静态函数并依靠优化器删除所有冗余代码。
在发布版本中,这应该是零成本:
#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';
}
#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
return 类型更改为 std::string
使其工作。
decltype
构造生成标识符或表达式的声明类型。当使用 return 类型声明 func
时,调用表达式 func()
的类型是已知的并且一切都按预期工作。
然而,当func
声明为return类型占位符auto
时,那么func
的声明取决于它的定义,因此 func
的类型以及表达式 func()
的类型在定义函数之前是未知的。
当您在 class 定义中内联定义一个 class 成员函数时,就好像该定义紧跟在 class 定义的结尾(即,函数体可能会引用在 class 定义中 later 词法声明的名称)。这个结果和 auto
的语义是你的函数 auto func
实际上没有完全 声明 直到 class 定义结束,并且因此 func()
的类型直到那时才能知道。
除了其他答案之外,一个可能的解决方法是将检查推迟到静态函数并依靠优化器删除所有冗余代码。
在发布版本中,这应该是零成本:
#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';
}