c++templatestemplate-specialization

Declaring a template that resolves to another template


I'm working with heavily templated code, where I've got a lot of "helpers" implementing somewhat common base functionality that's missing in the STL. For example:

// is_instance_v determines whether the type argument passed is an instance of the given template
// e.g. is_instance_v<std::vector<int>, std::vector> is true
template<typename, template<typename...> typename>
constexpr bool is_instance_v = false;
template<typename... Ts, template<typename...> typename U>
constexpr bool is_instance_v<U<Ts...>, U> = true;

This is a pretty useful little template. But now I've got other templates where I want to use this in a more generic way. I'd like if I could use is_instance_v as a template argument to something while only partially specifying type arguments. That way I can pass it to a template which takes a template parameter, and let it fill in the rest. Essentially, I want a template that turns into a template, like so:

// not working code - just the kind of thing I'm envisioning
template<template<typename> typename Template>
template<typename T>
using instance_comparator_t = is_instance_v<T, Template>;

// instance_comparator_t<std::vector> can now be passed to another template that expects a template<typename> arg

The above example however doesn't work. This is because, as I understand it, using declarations are for types, and this is a template.

Possible valid solutions I've thought of:

Is there a better way? I'm open to solutions for any version of C++, including upcoming ones.


Solution

  • You can wrap is_instance_v in a class template like as shown below:

    template<typename, template<typename> typename Template> struct Test
    {
       template<typename, template<typename...> typename>
       static constexpr bool is_instance_v = false;
       template<typename... Ts, template<typename...> typename U>
       static constexpr bool is_instance_v<U<Ts...>, U> = true;
    
    };
    
    template<typename T, template<typename> typename Template>
    using instance_comparator_t = Test<T, Template>;
    
    template<typename T, template<typename> typename Template>
    constexpr bool instance_comparator_v = instance_comparator_t<T, Template>::is_instance_v;