Похоже, что тот же подход, который вы можете использовать с типами или значениями, работает для шаблонов. Первые две строки показывают использование только с шаблонами и не требуют функций equals
или tag
или каких-либо аргументов для предоставленных шаблонов. Вторые два извлекают шаблоны из значений и выполняют те же тесты для них.
#include <iostream>
template<class...> struct A {};
template<class...> struct B {};
template<template<class...> class S>
struct Tag;
template<template<class...> class S>
struct Tag {
template<template<class...> class T>
constexpr auto equals(Tag<T>) -> std::false_type { return {}; }
constexpr auto equals(Tag<S>) -> std::true_type { return {}; }
};
template<template<class...> class T, class... V>
Tag<T> tag(T<V...> const&) { return {}; }
template<class S, class T>
auto equals(S && s, T && t) -> decltype(tag(s).equals(tag(t))) { return {}; }
int main(int argc, const char *argv[]) {
using namespace std;
cout << Tag<A>{}.equals(Tag<A>{}) << "; " << Tag<A>{}.equals(Tag<B>{}) << endl;
// 1; 0
cout << Tag<B>{}.equals(Tag<A>{}) << "; " << Tag<B>{}.equals(Tag<B>{}) << endl;
// 0; 1
A<float> af;
A<double> ad;
B<int> bi;
B<char, char> bcs;
cout << equals(af, ad) << "; " << equals(af, bi) << endl;
// 1; 0
cout << equals(bi, ad) << "; " << equals(bi, bcs) << endl;
// 0; 1
}