简体   繁体   English

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

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

The following program yields a compilation error with clang , though it passes on other compilers: 以下程序产生了与clang的编译错误,尽管它传递给其他编译器:

#include <utility>

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

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

int main()
{
  return 0;
}

clang yields: 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.

Is this program illegal, and if so, is there a correct way to define foo::bar_type ? 这个程序是非法的,如果是这样,有没有正确的方法来定义foo::bar_type

clang details: 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 issues the same error g ++ 4.9发出相同的错误

I'm not sure if this is an invalid code, because incomplete types are allowed for declval , and expression in decltype is not evaluated. 我不确定这是否是无效代码,因为declval允许不完整的类型,并且不评估decltype表达式。
rightføld in his answer explained very good why this code is invalid. rightføld在他的回答中解释了为什么这段代码无效。

You can use std::result_of : 你可以使用std :: result_of

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

Which is actually implemented like this: 这实际上是这样实现的:

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

The difference between this and the code in the question is that pointer-to-member operator ( .* ) is used instead of member access operator ( . ), and it doesn't require the type to be complete, which is demonstrated by this code: 这与问题中的代码之间的区别在于使用指向成员的操作符( .* )而不是成员访问操作符( . ),并且它不需要完成类型,这由此证明码:

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

§7.1.6.2 says: §7.1.6.2说:

For an expression e , the type denoted by decltype(e) is defined as follows: 对于表达式e ,由decltype(e)表示的类型定义如下:

  • if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e) is the type of the entity named by e . 如果e是未表示的id-expression或未加密的类成员访问(5.2.5),则decltype(e)e命名的实体的类型。 ...
  • ...

§5.2.5 says: §5.2.5说:

For the first option (dot) the first expression shall have complete class type. 对于第一个选项(点),第一个表达式应具有完整的类类型。 ...

§9.2 says: §9.2说:

A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. 一类被认为是在闭合完全定义的对象类型(3.9)(或完全型) }的类指定符。 ...

decltype(std::declval<foo>().bar()) (and in turn std::declval<foo>().bar() ) appears before the closing } , so foo is incomplete, so std::declval<foo>().bar() is ill-formed, so clang is correct. decltype(std::declval<foo>().bar()) (以及std::declval<foo>().bar() )出现在结束}之前,所以foo不完整,所以std::declval<foo>().bar()格式不正确,所以clang是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM