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

Jar*_*ock 11 c++ clang return-type-deduction

以下程序产生编译错误clang,但它传递给其他编译器:

#include <utility>

struct foo
{
  auto bar() -> decltype(0)
  {
    return 0;
  }

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

int main()
{
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

这个程序是非法的,如果是的话,有没有正确的方法来定义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
Run Code Online (Sandbox Code Playgroud)

Ant*_*vin 9

g ++ 4.9发出相同的错误

我不确定这是否是无效代码,因为允许不完整的类型declval,并且decltype不评估表达式.
rightføld在他的回答中解释了为什么这段代码无效.

你可以使用std :: result_of:

using bar_type = std::result_of<decltype(&foo::bar)(foo)>::type;
Run Code Online (Sandbox Code Playgroud)

这实际上是这样实现的:

using bar_type = decltype((std::declval<foo>().*std::declval<decltype(&foo::bar)>())());
Run Code Online (Sandbox Code Playgroud)

它与问题中的代码之间的区别在于使用指向成员的operator(.*)而不是成员访问operator(.),并且它不需要完成类型,这由以下代码演示:

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


rig*_*old 6

§7.1.6.2说:

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

  • if e是未加密码的id-expression或未加括号的类成员访问(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()是不正确的,所以铿锵是正确的.