Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use the `auto` keyword as a return type in a function pointer declaration with initialization?

The following code compiles successfully both with clang++ 3.8.0 and g++ 7.2.0 (the compilation flags are -std=c++14 -O0 -Wall -Wextra -Werror -pedantic-errors):

#include <iostream>


int foo_int(int)
{
    std::cout << "int foo(int)" << std::endl;

    return 0;
}

void foo_void(int)
{
    std::cout << "void foo(int)" << std::endl;
}

auto foo_auto_int(int)
{
    std::cout << "auto foo(int), auto == int" << std::endl;

    return 0;
}

auto foo_auto_void(int)
{
    std::cout << "auto foo(int), auto == void" << std::endl;

    return void();
}


int main()
{
    auto (*fi)(int) = foo_int;
    auto (*fv)(int) = foo_void;
    auto (*fai)(int) = foo_auto_int;
    auto (*fav)(int) = foo_auto_void;

    (void)fi(0);
    fv(0);
    (void)fai(0);
    fav(0);
}

Is it a valid C++ code?

Note that the decltype(auto) is rejected both by clang++ and g++ in the same situation.

like image 635
Constructor Avatar asked Dec 18 '17 15:12

Constructor


People also ask

What does the auto keyword before the function name mean?

In the case of functions, the auto keyword before the function name or the auto return type signifies that the return type of that function will be evaluated from the return type expressions at runtime. From C++ 11, this keyword was introduced; before that, the programmer needed to assign each variable’s data type explicitly at compile time.

When to initialize a variable declared with the auto keyword?

Note: The variable declared with auto keyword should be initialized at the time of its declaration only or else there will be a compile-time error. Note: We have used typeid for getting the type of the variables. Typeid is an operator which is used where the dynamic type of an object needs to be known.

Why can't I use the auto keyword to declare a type?

The auto keyword cannot be combined with any other type-specifier. A symbol that is declared with the auto keyword must have an initializer. You incorrectly used the auto keyword to declare a type. For example, you declared a method return type or an array. A parameter or template argument cannot be declared with the auto keyword.

How to use Auto to deduce the return type of a function?

Using auto to deduce the return type of a function in C++11 is way too verbose. First, you have to use the so-called trailing return type and second, you have to specify the return type in a decltype expression. You have to read the expression auto sum (T t, T2 t2) -> decltype (t + t2) in the following way.


1 Answers

The compilers are behaving correctly.

From [dcl.spec.auto]

The auto and decltype(auto) type-specifiers are used to designate a placeholder type that will be replaced later by deduction from an initializer.

[...]

auto or decltype(auto) shall appear as one of the decl-specifiers in the decl-specifier-seq and the decl-specifier-seq shall be followed by one or more declarators, each of which shall be followed by a non-empty initializer.

Which is saying auto and decltype(auto) can only be written with the specifiers you write in the front of a declaration (static, virtual etc), with their types deduced from the immediately following declarators with initializers.

The case of auto

The declarator in the case of auto (*fi)(int) = foo_int; is (*fi)(int) which is of the form

( ptr-operator declarator-id ) ( parameter-declaration-clause )

Hence auto (*fi)(int) = foo_int; is valid, provided the deduction succeeds, which it does. Likewise for the other few.

The case of decltype(auto)

From [dcl.spec.auto.deduct], given a type T containing a placeholder type

If the placeholder is the decltype(auto) type-specifier, T shall be the placeholder alone.

Which means adding anything else is illegal

int i;
decltype(auto)* p = &i;  // error, declared type is not plain decltype(auto)

Hence decltype(auto) (*fi)(int) = foo_int; is illegal.

like image 148
Passer By Avatar answered Oct 19 '22 06:10

Passer By