-1

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.

Lehu
  • 761
  • 4
  • 14
  • Do you want `using test_func_type_2 = int();`? – 273K Mar 07 '21 at 01:17
  • There's no such thing as a "reference to a function" in C++, only a "pointer to a function". – Sam Varshavchik Mar 07 '21 at 01:20
  • @S.M. That works. But why isn't `int (&)()` working? `test_func_type_1` and `test_func_type_2` have the same type (at least according to typeid) so as I see it both should work... – Lehu Mar 07 '21 at 01:21
  • 1
    @SamVarshavchik That's not really correct. There are function references. And you see one of the examples above. Other example: `int (&func_ref)(void) = test_func;` As for longer discussion: https://stackoverflow.com/questions/19200513/function-pointer-vs-function-reference – Lehu Mar 07 '21 at 01:26

1 Answers1

0

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.

cpplearner
  • 13,776
  • 2
  • 47
  • 72
  • That makes sense! I was surprised to get the same type for both `int (&) ()` and `int ()`. Thanks! – Lehu Mar 07 '21 at 02:13