尝试编译这个简单的类:
#include <vector>
struct M
{
// interface
auto begin() -> decltype(identities.begin())
{
return identities.begin();
}
// implementation
private:
std::vector<int> identities;
};
导致错误:
$ g++-510 where.cpp -std=c++11
where.cpp:57:35: error: ‘struct M’ has no member named ‘identities’
auto begin() ->decltype(this->identities.begin())
^
where.cpp:57:35: error: ‘struct M’ has no member named ‘identities’
$ clang++ where.cpp -std=c++11 -Wall -pedantic -Wextra
where.cpp:57:35: error: no member named 'identities' in 'M'
auto begin() ->decltype(this->identities.begin())
~~~~ ^
为什么没有decltype
看到班级成员?
答案 0 :(得分:22)
来自N3337 [basic.lookup.unqual] / 7:
在成员函数体或嵌套类定义之外的类X的定义中使用的名称应以下列方式之一声明:
- 在X类中使用之前或者是X的基类的成员,或者......
因为尾部返回类型是函数声明的一部分而不是定义,所以它无法预先看到在类中声明了什么,所以你需要在函数声明之上声明该成员。
答案 1 :(得分:16)
如果C ++ 14可用,您可以省略尾随返回类型,从而避免引用函数体外的成员并使代码更紧凑:
auto begin() {
return identities.begin();
}
一般来说,将decltype(auto)
用于此类转发方法更为正确,因此返回类型可以作为参考,但在这种特殊情况下它是相同的(感谢@Nawaz):
decltype(auto) begin() {
return identities.begin();
}
答案 2 :(得分:2)
在函数之前移动成员的声明,如下所示:
#include <vector>
struct M
{
// implementation
private:
std::vector<int> identities;
public:
// interface
auto begin() -> decltype(identities.begin())
{
return identities.begin();
}
};