如何从类中获取成员函数的返回类型

How to get the return type of a member function from within a class?

本文关键字:成员 函数 返回类型 获取      更新时间:2023-10-16

以下程序使用clang产生编译错误,尽管它会传递给其他编译器:

#include <utility>
struct foo
{
  auto bar() -> decltype(0)
  {
    return 0;
  }
  using bar_type = decltype(std::declval<foo>().bar());
};
int main()
{
  return 0;
}

clang产量:

$ clang -std=c++11 clang_repro.cpp 
clang_repro.cpp:10:48: error: member access into incomplete type 'foo'
  using bar_type = decltype(std::declval<foo>().bar());
                                               ^
clang_repro.cpp:3:8: note: definition of 'foo' is not complete until the closing '}'
struct foo
       ^
1 error generated.

这个程序是非法的吗?如果是,有没有正确的方法来定义foo::bar_type

clang详细信息:

$ clang --version
Ubuntu clang version 3.5-1ubuntu1 (trunk) (based on LLVM 3.5)
Target: x86_64-pc-linux-gnu
Thread model: posix

g++4.9发布相同错误

我不确定这是否是一个无效的代码,因为declval允许不完整的类型,并且decltype中的表达式不会被求值
rightføld在他的回答中很好地解释了为什么这个代码是无效的。

您可以使用std::result_of:

using bar_type = std::result_of<decltype(&foo::bar)(foo)>::type;

它实际上是这样实现的:

using bar_type = decltype((std::declval<foo>().*std::declval<decltype(&foo::bar)>())());

这与问题中的代码的区别在于,使用了指向成员运算符(.*)的指针,而不是成员访问运算符(.),并且它不需要类型完整,这一点可以通过以下代码来证明:

#include <utility>
struct foo;
int main() {
    int (foo::*pbar)();
    using bar_type = decltype((std::declval<foo>().*pbar)());
}

§7.1.6.2说:

对于表达式e,由decltype(e)表示的类型定义如下:

  • 如果e是未加括号的id表达式或未加括号类成员访问(5.2.5),则decltype(e)是由e命名的实体的类型

§5.2.5规定:

对于第一个选项(点),第一个表达式应具有完整的类类型…

§9.2规定:

在类说明符的结束}处,类被视为完全定义的对象类型(3.9)(或完整类型)…

decltype(std::declval<foo>().bar())(进而std::declval<foo>().bar())出现在闭合的}之前,所以foo是不完整的,所以std::declval<foo>().bar()是不成形的,所以clang是正确的。