Почему 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
не видит член класса?
Ответы
Ответ 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();
}
};