为什么 std::thread 接受通用 lambda 但不接受模板化函数(没有显式实例化)?

ale*_*833 4 c++ lambda templates stdthread

为什么在没有任何专门化的情况下将通用 lambda 传递给 std::thread() 是合法的,而另一方面,这对于函数模板来说是非法的。

下面演示了我的查询。

#include <thread>

template <class T>
void f(T t)
{
}

int main()
{
    std::thread t([](auto i){}, 1);  // Works
    std::thread t(f, 1);          // Doesn't work
    std::thread t(f<int>, 1);     // Works

    t.join();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Sam*_*hik 9

C++ 由许多不同种类的东西组成。其中一些是:对象、类型和模板。它们是完全不同的东西,有自己独特的目的。C++ 程序中有正确的位置使用对象、正确的位置使用类型以及正确的位置使用模板。当您为对象找到合适的位置时,就无法使用类型或模板。当您有正确的位置来使用类型时,您就不能使用对象或模板。当您有正确的位置来使用模板时,您就不能使用对象或类型。这是 C++ 的基础。

函数调用或构造函数的参数始终是对象。它们从来都不是类型或模板。

    std::thread t([](auto i){}, 1);  // Works
Run Code Online (Sandbox Code Playgroud)

两个参数都是对象。这是对的。lambda 是一个对象,是唯一的匿名类型的实例。1也是一个对象:一个值为 1 的整数。

    std::thread t(f, 1);          // Doesn't work
Run Code Online (Sandbox Code Playgroud)

f不是一个对象。它是一个模板。

    std::thread t(f<int>, 1);     // Works
Run Code Online (Sandbox Code Playgroud)

f<int>是一个对象,一个指向从模板实例化的函数的指针。

与模板名称相对应的标识符本身会产生模板。它不会产生类型或对象。当您指定模板参数时,您最终会得到一个类型,并且在引用模板函数的类型的特殊情况下,您将获得一个指向模板函数实例的指针,一个对象(就像使用普通非模板的名称一样)函数本身给你一个指向该函数的指针)。