简体   繁体   中英

partial specialization on the number of template parameters of template template parameter

Let's say I have a template like this:

template<template<typename...> class>
struct MyTrait;

MyTrait accepts a template with any number of parameters as parameter. Now I need to know the number of template parameters of the template passed to MyTrait . But a specialization like below doesn't work.

template<template<typename> class T>
struct MyTrait<T> {}; // error: partial specialization cannot match argument list for primary template

template<template<typename, typename> class T>
struct MyTrait<T> {};

At the bottom of this answer, there is more information and examples on how such an issue can be resolved.

But to be more specific to your question, partial specialization on the number of parameters of a template template parameter cannot be done. At least, not the way you are trying to do it...

A partial specialization is usually made on a type . It can be done for a template parameter, but in this case, the different specializations must name a template, and each specialization must be done for a template having the same number of parameters.

This might be an explanation of why the way you tried to define the specialization is not allowed...

That said, it is possible to make specializations of a template having a typename parameter for types that are containers . That is, templates having the type of their parameters already 'declared' . I've use the word 'declared' on purpose...

Indeed, as I have demonstrated within the answer to "Get number of template parameters with template template function" here , it is possible to inject "random" parameters into a template without instantiating it .

This characteristic can be used in many different ways to define specializations of a template for ie:

  • Branching.
  • Dispatching.
  • Derive from different implementations.
  • Etc...

The code at the bottom of this answer (taken as-is from another answer of mine) , shows a simple way to take advantage of this tool that the language offers...


° How can one do such a specialization ?

  • For a more detailed answer, see my answer here

But to prevent you from going here and there to find some working code, the code here below is a solution that can be used to specialize a template based on a template template parameter.

It should be self-explanatory...

// Helper to make the static_assert 'name-dependent'.
template<typename...> using AlwaysFalse = std::false_type;

// Primary template should only signal the error...
template<typename Trait>
struct ImplSelect {
    static_assert(
        AlwaysFalse<Trait>::value,
        "Missing specialization..."
    );
};

// Specialization for a template with one type parameter.
template<template <typename> class Trait, typename T>
struct ImplSelect<Trait<T>> { using Type = Trait<int>; };

// Specialization for a template with two type parameters.
template<template <typename, typename> class Trait, typename T, typename U>
struct ImplSelect<Trait<T, U>> { using Type = Trait<int, int>; };

/* [ Note ] These are ONLY forward declarations.
 *          They aren't instatiated within this code.
 */
template<typename T>             struct Victim1;
template<typename T, typename U> struct Victim2;

/* [ Note ] Opaque type tags (forward declarations).
 *          Allows for further tag dispatching if desired.
 */
struct Tag1; struct Tag2;

/* Selection of Victim1<int> and Victim2<int, int>.
 * Not instantiated yet...
 */
using Impl1 = typename ImplSelect<Victim1<Tag1>>::Type;
using Impl2 = typename ImplSelect<Victim2<Tag1, Tag2>>::Type;
Enjoy !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM