In C++11 it's fine to declare a function like
auto times2(double num) -> double; // A
and define it like
double times2(double num) { // B
return num*2;
}
The pair A, B
can also be mixed the other way around.
C++14 introduces a third way
auto times2(double num) { // C
return num;
}
C
be mixed with A / B
in a declaration/definition pair ?Can C
stand alone as a signature (when the body of the function is not yet provided) ?
// waiting for the definition to provide info on return type
auto times2(double);
In C++, Forward declarations are usually used for Classes. In this, the class is pre-defined before its use so that it can be called and used by other classes that are defined before this. Example: // Forward Declaration class A class A; // Definition of class A class A{ // Body };
A forward declaration allows us to tell the compiler about the existence of an identifier before actually defining the identifier. In the case of functions, this allows us to tell the compiler about the existence of a function before we define the function's body.
To declare a subroutine, use one of these forms: sub NAME ; # A "forward" declaration. sub NAME ( PROTO ); # Ditto, but with prototype.
7.1.6.4p13
auto
specifier[dcl.spec.auto]
Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type.
The above quotation makes it ill-formed to mix the new with the old.
More specifically any such mixing introduces an ambiguating since the only difference in the two declarations is the return-type of the function; two declarations where one uses auto
and the other a non-deduced type T
are, in other words, not referring to the same function.
auto f ();
auto f () { return 123; } // legal, return type is `int`
auto g ();
auto g () -> int; // ill-formed, an invalid overload of `g` introduced
int h ();
auto h (); // ill-formed, an invalid overload of `h` introduced
There are rules related to automatic return-type deduction in C++14 that states that a function which yet hasn't had its return-type deduced is not usable in a context where such is required, that means that (A) below is not equivalent of an old-school declaration (ie. that a function can be used without yet having the definition).
auto foobar (double); // (A)
int main () {
auto ret = foobar(3.14f); // ill-formed, return type is not known (yet)
}
...
7.1.6.4p9
auto
specifier[dcl.spec.auto]
If the type of an entity with an undeduced placeholder type is needed to determine the type of an expression the program is ill-formed. ...
auto
is... useless?No, far from it, there are cases where a forward declaration certainly is required and contexts where the return-type mustn't be known until a later time, such as inside a template.
template<class T>
auto foobar (T);
template<class T>
auto barbaz (T val) { return foobar (val); }
template<class T>
auto foobar (T val) { return val * 2; }
int main () {
barbaz (1234); // return-type is int
barbaz (3.1f); // return-tupe is float
}
Inside barbaz
we must not know the return-type of foobar
until we have actually instantiated barbaz
, but without the a forward declaration of auto foobar(T)
we couldn't refer to such name inside our template.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With