-->

Why isn't std::function a valid template param

2020-06-01 04:10发布

问题:

I have defined class template named CallBackAtInit which only purpose is to call a function at its initialization (constructor). The function is specified in template parameters. The problem is that templates does not accept std::function as parameters; but they accept function pointers. Why?

Here is my code:

#include <iostream>
#include <functional>

/* Does not work:*/     template <typename return_type, typename arg_type, std::function<return_type(arg_type)> call_back>
/* Work fine: *///      template <typename return_type, typename arg_type, return_type(*call_back)(arg_type)>

class CallBackAtInit {
public:
    CallBackAtInit(arg_type arg)
    {
        call_back(arg);
    };
};

void printInt(int i);

class HoldInt : private CallBackAtInit<void, int, printInt> {
public:
    HoldInt(int integer)
    : CallBackAtInit(integer)
    {}
    // ...
};

int main(int argc, char** argv)
{
    HoldInt hi(10);
    return 0;
}

void printInt(int i)
{
    std::cout << i << std::endl;
}

回答1:

The parameter for a template definition can be of four kinds:

  • parameter which can accept only type (or template type).
  • parameter which can accept only integral value.
  • parameter which can accept only pointer-to-member value.
  • std::nullptr_t (since C++11)

When you mention std::function in a template definition, then it falls neither of the above categories. The template cannot accept types, nor can it accept integral value, or pointer-to-member value.

When the parameter is function pointer type, then it can accept function-pointer (the address of a function matching the type) which is just an integral value. Note that address is always an integral value. So it falls into the second category, which is why it works.



回答2:

Because it's not allowed by the standard:

14.1 Template parameters

4 A non-type template-parameter shall have one of the following (optionally cv-qualified) types:

— integral or enumeration type,

— pointer to object or pointer to function,

— lvalue reference to object or lvalue reference to function,

— pointer to member,

— std::nullptr_t.