Как объявить функцию, тип возврата которой выведен?

Рассмотрим этот С++ 1y код (LIVE EXAMPLE):

#include <iostream>

auto foo();

int main() {
    std::cout << foo();   // ERROR!
}

auto foo() {
    return 1234;
}

Компилятор (GCC 4.8.1) щедро снимает эту ошибку:

main.cpp: В функции 'int main():
main.cpp: 8: 18: ошибка: использование 'auto foo() перед выводом' auto      std:: cout < Foo();
                    ^

Как мне переслать-объявить foo() здесь? Или, может быть, более правильно, можно переслать-объявить foo()?


Я также попытался скомпилировать код, где я попытался объявить foo() в файле .h, определенном foo() так же, как и выше, в файле .cpp, включил .h в мой main.cpp, содержащий int main() и вызов foo(), и построил их.

Произошла одна и та же ошибка.

Ответ 1

В соответствии с этой статьей было предложено в N3638, это явно справедливо.

Соответствующий фрагмент:

[ Example:

auto x = 5;                  // OK: x has type int
const auto *v = &x, u = 6;   // OK: v has type const int*, u has type const int
static auto y = 0.0;         // OK: y has type double
auto int r;                  // error: auto is not a storage-class-specifier
auto f() -> int;             // OK: f returns int
auto g() { return 0.0; }     // OK: g returns double
auto h();                    // OK, h return type will be deduced when it is defined
— end example ]

Однако он продолжает:

Если тип объекта с неопределенным типом-заполнителем необходим для определения типа выражения, программа плохо сформирована. Но как только оператор return был замечен в функции, возвращаемый тип, выводимый из этого оператора, может использоваться в остальной части функции, в том числе в других операторах return.

[ Example:

auto n = n; // error, n type is unknown
auto f();
void g() { &f; } // error, f return type is unknown
auto sum(int i) {
  if (i == 1)
    return i;  // sum return type is int
  else
    return sum(i-1)+i; // OK, sum return type has been deduced
}
—end example]

Таким образом, тот факт, что вы использовали его до его определения, вызывает ошибку.