When can automatic return type apply?

c++, c++14

Solution

Introduction

There are a few simple rules that states when the return-type of a function can be deduced from the function body, and with that when `auto` is applicable as return-type.

These rules are all stated in the Standard (n3797) [1], and each rule is listed in it's own section in the remaining parts of this post.

[1] in section 7.1.6.4, auto specifier `[dcl.type.elab]`.

Is there anything that can't be deduced using `auto` as the return-type?

`[dcl.type.elab]p1` If the deduction is for a `return` statement and the initializer is a braced-init-list (8.5.4), the program is ill-formed.

auto func () { return {1,2,3}; } // ill-formed

Which type will be deduced if a function has more than one return-statement?

`[dcl.type.elab]p9` If a function with a declared return type that contains a placeholder type has multiple return statements, the return type is deduced for each return statement. If the type deduced is not the same in each deduction, the program is ill-formed.

auto gunc_1 (bool val) { // (1), ill-formed
  if (val) return 123;
  else     return 3.14f;
}
auto gunc_2 (bool val) { // (2), legal
  if (val) return static_cast<float> (123);
  else     return 3.14f;
}

Note: (1) is ill-formed since all return-statements are not of the same type, whereas (2) is legal since the two return-statements yields the same type.

What happens if the function doesn't have a return-statement?

`[dcl.type.elab]p10` If a function with a declared return type that uses a placeholder type has no return statements, the return type is deduced as though from a return statement with no operand at the closing brace of the function body.

auto hunc () { } // legal, return-type is `void`

Can I use the function, before the return-type has been deduced?

`[dcl.type.elab]p11` 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. Once a return statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other return statements.

auto junc (); // declaration

void foo () { &junc; } // (1), ill-formed

auto junc () { // definition
   return 123;
}

void bar () { &junc; } // (2), legal
auto recursive (int x) {
  if (--x) return x + recursive (x); // (3), ill-formed
  else     return 0;
}

Note: We cannot take the address of `junc` inside `foo` since doing that requires knowledge about what the complete type of `junc` is, something which isn't know until we have provided a definition where the return-type has been deduced. (2) is therefor legal, whereas (1) isn't.

Note: (3) is also ill-formed since we must know the return-type of `recursive` at this point, but it isn't known. Having the return-statements in the opposite order would, however, be valid. That way the compiler would know `recursive` to return `int` when it hits `return x + recursive (x)`.

Problem

What are the rules, that allow writing automatic return types in c++1y ? ``` #include <iostream> using namespace std; template<typename T1, typename T2> auto f(T1 const& a, T2 const &b) { if (a > b) return a-b; else return a+b; } int main() { cout << f(1, 2.) << endl; return 0; } ``` Is there a limit imposed by the cyclomatic complexity of a function's body?

Original source

Related problems