Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a template template argument without specifying the concrete type

I would like to implement a wrapper around a function call that would do something like this:

template <template<class> class F>
void Wrapper(int n, F&& f)
{
    switch (n)
    {
        case 1:
            f<std::int8_t>();
            break;
        case 2:
            f<std::int16_t>();
            break;
        default:
            break;
    }
}

template <class T>
void func()
{
    // ... body of func()
}

So that I would be able to make the following call in the code:

Wrapper(1, func);

But the abovementioned code doesn't compile because F&& f construct is invalid - I need to specify the concrete type of the argument. But if I make the function signature the following:

template <template<class> class F, class T>
void Wrapper(int n, F<T>&& f)

then I must make the call with the concrete type of f:

Wrapper(1, func<std::int8_t>);

and I won't be able to make a switch in Wrapper.

How can I implement the behaviour I need?

like image 929
undermind Avatar asked Oct 18 '18 14:10

undermind


People also ask

Can we pass non-type parameters to templates?

Template non-type arguments in C++It is also possible to use non-type arguments (basic/derived data types) i.e., in addition to the type argument T, it can also use other arguments such as strings, function names, constant expressions, and built-in data types.

How do I restrict a template type in C++?

There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.

What is meant by the template parameter it can be used to pass a type as an argument it can be used to evaluate a type it can of no return type it can be used to delete a type?

A template parameter is a specific form of the parameter that can be used to pass a type as an argument. These parameters can be used by these function templates just like any other ordinary type.


1 Answers

If you know func at compile time (that is, if it is not some function pointer), you can use the following solution:

template <template <class> typename F>
void Wrapper(int n) {
  switch (n) {
    case 1: F<std::int8_t>{}(); break;
    case 2: F<std::int16_t>{}(); break;
    default: break;
  }
}

template <typename T>
void func() { std::cout << sizeof(T) << std::endl; }

template <typename T>
struct Func { void operator()() { func<T>(); } };

int main() {
  Wrapper<Func>(1);
  Wrapper<Func>(2);
}
like image 145
Daniel Langr Avatar answered Oct 05 '22 21:10

Daniel Langr