以下程序会产生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
答案 0 :(得分:9)
我不确定这是否是无效代码,因为 declval
允许不完整的类型,并且不评估decltype
中的表达式。
rightføld in his answer非常清楚为什么这段代码无效。
您可以使用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)());
}
答案 1 :(得分:6)
§7.1.6.2说:
对于表达式
e
,decltype(e)
表示的类型定义如下:
- 如果
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()
格式不正确,所以铿锵是对的。