8

I would like to know how to write a type_traits class to detect whether two types are specializations of the same template class. The big problem is that it should work for mixed types/non-types template class like:

template <typename T, std::size_t N>
class MyClass {};

Is it possible to design a such thing?

Vincent
  • 57,703
  • 61
  • 205
  • 388
  • @rhalbersma, not a duplicate, the other question wants to know how to tell if two specializations use the same definition, i.e. are both using the primary template, or both using the same partial specialization, or both using the same explicit specialization. That's not the question here, as far as I can tell. – Jonathan Wakely Apr 22 '13 at 12:20
  • @Vincent, does the trait need to work for detecting uses of _any_ class template, or just for `MyClass`? I don't think it's possible in general for class templates using a mix of type and non-type parameters. – Jonathan Wakely Apr 22 '13 at 12:22
  • @JonathanWakely removed the comment, don't seem to be able to withdraw close vote. – TemplateRex Apr 22 '13 at 12:26
  • @JonathanWakely: no it should work for any mix of type/non-type template parameters and that's the whole problem... – Vincent Apr 22 '13 at 14:03
  • Basically, you want to do meta meta programming -- write programs over the domain of meta programs (`template`s). C++ meta meta programming facilities are limited. With `template< using typename T,` syntax that might be coming in C++17 you might be able to get closer, but right now you could follow the "variardic emulation" pattern that C++03 uses to emulate `template – Yakk - Adam Nevraumont Apr 24 '13 at 13:56

1 Answers1

2

I don't think you can do this in general for an arbitrary class template with a mix of type and non-type parameters.

You can get close for more specific sets of parameters, but I don't know any way to handle the general case:

#include <type_traits>

template <typename T, std::size_t N>
class MyClass {};

// assume not the same
template<typename T, typename U>
struct my_trait : std::false_type
{ };

// both specializations of MyClass
template<typename T1, std::size_t N1, typename T2, std::size_t N2>
struct my_trait<MyClass<T1, N1>, MyClass<T2, N2>>
: std::true_type
{ };

// both specializations of some class template Templ<typename, std::size_t>
template<template<typename, std::size_t> class Templ, typename A1, std::size_t S1, typename A2, std::size_t S2>
struct my_trait<Templ<A1, S1>, Templ<A2, S2>>
: std::true_type
{ };

// both specializations of some class template Templ<typename...>
template<template<typename...> class Templ, typename... A1, typename... A2>
struct my_trait<Templ<A1...>, Templ<A2...>>
: std::true_type
{ };
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • 1
    `decltype` on `templateclass U> T get_scalar( U );` will let you find scalar types if you already know the scalar/nonscalar pattern. We do not have a "I'll take `template`s, any scalar, or `typename`s" wildcard template argument however. – Yakk - Adam Nevraumont Apr 27 '13 at 13:39
  • 1
    C++17 has simplified this somewhat, since you can declare a template parameter `auto`. Now the problem is 'just' type vs. value vs template template parameters. – David Stone May 04 '21 at 03:06