Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto deduced return types in forward declaration and mixing with old function syntax

Intro

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;
}

Q

  1. Can style C be mixed with A / B in a declaration/definition pair ?
  2. 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); 
    
like image 354
Nikos Athanasiou Avatar asked Jun 09 '14 07:06

Nikos Athanasiou


People also ask

How do you forward a declaration function in C++?

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 };

Why use forward declarations C++?

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.

How do you perform a forward declaration of a subroutine performed?

To declare a subroutine, use one of these forms: sub NAME ; # A "forward" declaration. sub NAME ( PROTO ); # Ditto, but with prototype.


1 Answers

Mixing the new- and old-school

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

Is a function declaration using C++14's return-type deduction equivalent of a forward declaration?

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. ...


Are you saying that a declaration where the return-type is 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.

like image 193
Filip Roséen - refp Avatar answered Oct 11 '22 18:10

Filip Roséen - refp