Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass the name of a template class to a template argument?

Tags:

c++

templates

I know we can do the following,

template <class CONTAINER>
void f(CONTAINER *c){}

int main(){
    std::vector<int> v;
    f(&v);
    std::set<int> s;
    f(&s);
}

Then, I want an alternative (convenient for my project), like the following,

template <class CONTAINER>
void f(CONTAINER<int> *c){} // the CONTAINER is the name of a template class

But, the compiler outputs

error: ‘CONTAINER’ is not a template

Is this possible?

like image 243
user9985127 Avatar asked Sep 12 '25 00:09

user9985127


1 Answers

You are looking for a template template parameter:

#include <set>
#include <vector>

template<template<typename> typename CONTAINER>
void f(CONTAINER<int> *){}

int main(){
    std::vector<int> v;
    f(&v);
    std::set<int> s;
    f(&s);
}

"Matching template template parameters to compatible arguments" is a C++17 feature. This won't work with C++14 because std::vector has more than one template parameter.

You need -frelaxed-template-template-args to compile this code with Clang, see: Template template parameter in function templates and How is P0522R0 breaking code?

An alternative way is to use template template parameters with variadic templates to avoid "Matching template template parameters to compatible arguments":

#include <set>
#include <vector>

template<class T, template<class, class...> class CONTAINER, class... Args>
void f(CONTAINER<T, Args...> *){}

int main(){
    std::vector<int> v;
    f(&v);
    std::set<int> s;
    f(&s);
}

or

#include <set>
#include <vector>

template<template<class, class...> class CONTAINER, class... Args>
void f(CONTAINER<int, Args...> *){}

int main(){
    std::vector<int> v;
    f(&v);
    std::set<int> s;
    f(&s);
}

This works with C++11.

like image 188
Thomas Sablik Avatar answered Sep 13 '25 14:09

Thomas Sablik