[英]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 bydecltype(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 bye
.如果
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.