为什么decltype没有看到成员声明?

时间:2015-07-03 09:10:42

标签: c++ c++11

尝试编译这个简单的类:

#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看到班级成员?

3 个答案:

答案 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();
     }


};