为什么这些功能签名不一样?

Zeb*_*ish 7 c++ lambda templates function-pointers function

我一定是误会了,因为我认为这两种情况是一样的:

#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

    }
Run Code Online (Sandbox Code Playgroud)

现在,在这两种情况下,我的编译器都说函数签名是相同的,void function()和void lambdaFunc().我真的认为当lambda函数没有捕获任何东西时,它的行为就像一个自由函数,相同的签名似乎都支持它.此外,我想我更加困惑,因为在下面所有似乎都被视为同样的事情,就像腐烂到同一件事:

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
}
Run Code Online (Sandbox Code Playgroud)

因此,据我所知,函数和函数指针之间的唯一区别是当作为vector的模板参数给出时.这显然意味着我不太了解模板,但是这是什么原因?因为我试过的例子中两者看起来真的相同.

M.M*_*M.M 2

std::vector<void()>不允许; 类型必须是对象类型,而函数类型不是对象类型。

我们可以将向量需求规范的各个部分识别为非对象类型所违反的;最明显的是默认分配器。在 [allocator.requirements]/2 的表中指定分配器的类型必须是对象类型。