std::function with alias declaration gives incomplete type compiler error

I was playing with std::function and encountered behavior that I don’t understand. I was hoping someone could explain to me what’s going on in the code at the bottom of the question.

Providing function type directly of course works. Simiralry with typedef. The “fun” part begins when I use alias declaration (two commented out lines). Declaring type with using results in compiler giving me an error:

[build] /home/lehu/workspaces/cpp-learning/std-func/main.cpp: In function ‘int main()’:
[build] /home/lehu/workspaces/cpp-learning/std-func/main.cpp:17:37: error: aggregate ‘std::function<int (&)()> func2’ has incomplete type and cannot be defined
[build]    17 |     std::function<test_func_type_2> func2;
[build]       |                                     ^~~~~
[build] gmake[2]: *** [std-func/CMakeFiles/std-func.dir/build.make:82: std-func/CMakeFiles/std-func.dir/main.cpp.o] Błąd 1

I checked the types and typeid shows that both test_func_type_1 and test_func_type_2 have the same type (following is output of the program):

1
FivE
FivE

If the types are the same, why one version works and other doesn’t?!?

The code I was fiddling with:

#include <functional>
#include <iostream>

int test_func() {
    return 10;
}

int main() {
    std::function<int()> func;   //providing function type directly is ok
    func = test_func;

    typedef int (test_func_type_1)();
    std::function<test_func_type_1> func1;  //typedef works as well
    func1 = test_func;

    using test_func_type_2 = int (&) ();  //alias declaration is ok (can't use function pointer!)
    //std::function<test_func_type_2> func2; <-- here we get compiler error
    //func2 = test_func;

    std::cout << (typeid(test_func_type_1) == typeid(test_func_type_2) ) << std::endl;

    std::cout << typeid(test_func_type_1).name() << std::endl;
    std::cout << typeid(test_func_type_2).name() << std::endl;
    return 0;
}

EDITS

  1. It is true that changing
using test_func_type_2 = int (&) ();

into

using test_func_type_2 = int ();

results in error disappearing. However I would like to understand why my version is not compiling even if the types are aparently the same.

Answer

int (&) () and int () are not the same type. The former is reference to the latter. typeid gives the same result because it ignores referenceness.

[expr.typeid]/4:

If the type of the type-id is a reference to a possibly cv-qualified type, the result of the typeid expression refers to a std​::​type_­info object representing the cv-unqualified referenced type.

Leave a Reply

Your email address will not be published. Required fields are marked *