Подтвердить что ты не робот

Почему declitype не видит объявления участника?

Попытка скомпилировать этот простой класс:

#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 не видит член класса?

4b9b3361

Ответ 1

От N3337 [basic.lookup.unqual]/7:

Имя, используемое в определении класса X вне тела функции-члена или определения вложенного класса, должно быть объявлено одним из следующих способов:

  • перед его использованием в классе X или быть членом базового класса X или...

Поскольку возвращаемый тип возврата является частью объявления функции, а не определения, он не может смотреть вперед, чтобы узнать, что еще объявлено в классе, поэтому вам нужно объявить этот элемент выше объявления функции.

Ответ 2

Если С++ 14 доступен, вы можете опустить возвращаемый тип возврата, тем самым избегая ссылки на элемент вне тела функции, а также делая код более компактным:

auto begin() {
    return identities.begin();
}

В целом, более корректно использовать decltype(auto) для таких методов пересылки, поэтому возвращаемый тип может быть ссылкой, хотя в этом конкретном случае он одинаковый (благодаря @Nawaz):

decltype(auto) begin() {
    return identities.begin();
}

Ответ 3

Переместить объявление элемента перед функцией следующим образом:

#include <vector>
struct M
{
   // implementation
   private:
      std::vector<int> identities;
   public:    
   // interface
     auto begin() -> decltype(identities.begin())
     {
        return identities.begin();
     }


};