Search code examples
c++c++11templatesc++14template-templates

How to inspect the interface of a template template class


I was trying to overload a template class with SFINAE based on whether a template template parameter had the type type defined in it (for example std::remove_reference has a type member type alias), but I cannot figure out a good way to go about doing that.

For example, I wanted to do

template <template <typename...> class Trait>
using EnableIfHasTypeMember = std::void_t<Trait::type>;

template <template <typename...> class Trait, typename OtherStuff,
          EnableIfHasTypeMember<Trait>* = nullptr>
class Something { ... }

But this gives me a compiler error. Is there any way I can go about inspecting the interface of a template template parameter?


Solution

  • If I understand correctly what you're wanting, it's not possible with the level of generality that you showed in your example. You can't know whether the template has a type member type alias unless you know the arguments it's instantiated with, because it could differ based on the specialization. Example:

    template <typename T>
    struct my_trait
    {
        using type = int;
    };
    
    template <>
    struct my_trait<double> {};
    

    How would you expect EnableIfHasTypeMember to behave in this case? That's why you can't reason about the contents of a template until it is instantiated.

    It helps in situations like this to keep in mind that all instantiations of my_trait<T> for different types T are distinct types from one another. There is no actual relationship between the types; they originated from a common template, which admits the ability to write a generic implementation that is reused, but the concrete types once instantiated are wholly separate.