Я получил компиляцию ошибок ниже кода.
struct B{
double operator()(){
return 1.0;
}
};
struct A {
auto func() -> decltype(b())
{
return b();
}
B b;
};
Однако, если я реорганизую A
, он компилируется.
gcc 4.8 сказал, что 'b' не был объявлен в этой области.
struct A {
B b;
auto func() -> decltype(b())
{
return b();
}
};
Итак, что не так с первым?
Ответ 1
Определение class
обрабатывается двумя проходами: сначала собираются объявления участников, включая сигнатуры функций, а затем анализируются тела определений.
Таким образом, тело функции имеет доступ ко всем объявлениям участников, включая последующие, но прототип функции видит только предшествующие объявления.
Ответ 2
Действительно ли это?
Ваш последний пример хорошо сформирован, а первый - нет (так что GCC правильно).
Параграф 3.4.1/7 о неквалифицированном поиске имен указывает:
Имя, используемое в определении класса X
вне тела функции-члена, аргумент по умолчанию, скобка-или- равный-инициализатор нестатического элемента данных или определение вложенного класса должно быть объявлено в одном из следующие способы:
- перед его использованием в классе X
или быть членом базового класса X (10.2) или
- [...]
И что следует за другими условиями, которые не применяются в вашем случае.
Ответ 3
Вы также можете заставить его работать следующим образом:
struct B
{
double operator()()
{
return 1.0;
}
};
// my implementation does not have std::declval
template < typename T > T&& declval();
struct A
{
B b;
auto func() -> decltype(declval<B>().operator()())
{
return b();
}
};
изменить:
или поскольку B в области видимости уже в любом случае не нуждается в auto, → decltype и declval
struct A
{
B b;
decltype(Q()()) func()
{
return b();
}
};