У меня возникли проблемы с пониманием того, как расширение C ++ 14 auto
спецификатор типа, описанный в N3638 может быть реализовано, и что, собственно, разрешено.
В частности, одно из изменений в стандарте гласит:
Если объявленный тип возврата функции содержит тип заполнителя, тип возврата функции выводится из операторов возврата в теле функции, если таковые имеются.
Достаточно легко увидеть, как это работает, когда тело функции находится в том же файле, что и объявление; но рассмотрим случай, когда заголовочный файл объявляет метод, использующий auto
заполнитель, но не определяет Это. Как переводить блоки, которые включают этот заголовочный файл, но делают не включить файл, который определяет метод, будет успешно скомпилирован?
Например, учитывая файл foo.hpp
:
class foo
{
public:
auto gen_data();
};
…и файл foo.cpp
:
struct data_struct
{
int a;
int b;
int c;
double x;
char data[37];
};
auto foo::gen_data()
{
data_struct d;
// initialize members in d...
return d;
}
…и файл main.cpp
:
#include "foo.hpp"
template<typename T>
double get_x(T f)
{
return f.gen_data().x;
}
int make_and_get_x()
{
foo f;
return get_x<foo>(f);
}
…законно ли компилировать main.cpp
сам по себе? Если нет, то почему нет? Если так, то как get_x
экземпляр, так как компилятор не может знать, является ли возвращаемый тип gen_data
даже есть член по имени x
не говоря уже о его смещении?
Похоже, что это будет проблемой, даже не беспокоясь о реализации шаблона; например, что произойдет, если вы попытаетесь получить доступ f.gen_data().x
напрямую или передавая его функции?
Применимое правило находится в §7.1.6.4 [dcl.spec.auto] / p11:
Если требуется тип сущности с неопределенным типом заполнителя
чтобы определить тип выражения, программа плохо сформирована.
Есть пример:
auto f();
void g() { &f; } // error, f’s return type is unknown
Вам нужен тип gen_data
определить тип выражения x.gen_data()
; следовательно, программа плохо сформирована. Чтобы использовать такую функцию, определение должно быть видимым для компилятора.