Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why aren't these function signatures treated the same?

I must be misunderstanding something because I thought the two cases are the same:

#include <iostream>

    void function() { std::cout << "Hi\n"; }

    int main()
    {
        std::vector<void(*)()> funcPtrVec;
        std::vector<void()> funcVec;

        funcPtrVec.push_back(function); // Works 
        funcVec.push_back(function);    // Works

        auto lambdaFunc = []() { std::cout << "Hi\n"; };

        funcPtrVec.push_back(lambdaFunc);   // Works
        funcVec.push_back(lambdaFunc);      // Doesn't work

    }

Now, in both cases my compiler says that the function signatures are the same, void function() and void lambdaFunc(). I really thought that when a lambda function doesn't capture anything it behaves like a free function, which the same signatures would seem to support. Also, I guess I'm confused even more due to the fact that in the following all seem to be treated the same, as if decaying to the same thing:

void function() { std::cout << "Hi\n"; }

void funcTakingFunc(void()) {}
void funcTakingFuncPtr(void(*)()) {}

int main()
{
    auto lambdaFunc = []() { std::cout << "Hi\n"; };
    void(*funcPtr)() = lambdaFunc;  // Works

    funcTakingFuncPtr(lambdaFunc);  // Works
    funcTakingFuncPtr(funcPtr);     // Works
    funcTakingFunc(lambdaFunc);     // Works
    funcTakingFunc(funcPtr);        // Works
    // They all work
}

So as far as I can see the only distinction between the function and the function pointer made is when given as a template argument to vector. This obviously means I don't understand templates well, but what's the reason for this? Because the two really seem the same from the examples I tried.

like image 958
Zebrafish Avatar asked Sep 22 '17 22:09

Zebrafish


1 Answers

std::vector<void()> is not allowed; the type must be an object type, and a function type is not an object type.

There are various parts of the specification of vector requirements we could identify as being violated by a non-object type; the most obvious is the default allocator. In the table in [allocator.requirements]/2 it is specified that the type the allocator is for must be an object type.

like image 156
M.M Avatar answered Oct 20 '22 16:10

M.M