Search code examples
c++templateslambdastdthread

Why std::thread accepts generic lambdas but not templated functions (without explicit instantiation)?


Why is it legal to pass generic lambdas to std::thread() without any specialization, while, on the other hand, this is illegal with function templates.

The following demonstrates my query.

#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;
}

Solution

  • C++ consists of many different kinds of things. Some of these things are: objecs, types, and templates. They are completely different things, that serve their own distinct, unique purposes. There's a right place in a C++ program to use an object, a right place to use a type, and a right place to use a template. When you have a right place for an object, you can't use a type or a template. When you have a right place to use a type you can't use an object or a template. When you have a right place to use a template you can't use an object or a type. This is fundamental to C++.

    The parameters to a function call, or a constructor, are always objects. They are never types, or templates.

        std::thread t([](auto i){}, 1);  // Works
    

    Both parameters are objects. This is correct. A lambda is an object, an instance of a unique, anonymous type. 1 is also an object: an integer whose value is 1.

        std::thread t(f, 1);          // Doesn't work
    

    f is not an object. It is a template.

        std::thread t(f<int>, 1);     // Works
    

    This f<int> is an object, a pointer to a function that was instantiated from a template.

    An identifier that corresponds to a name of a template, by itself, results in a template. It does not result in a type, or an object. When you specify template parameters you end up with a type, and in a special case of a type that refers to a template function you get a pointer to the template function instance, an object (just like using the name of an ordinary non-template function, by itself, gives you a pointer to that function).