I had an idea for a template comparator analogous to std::is_same
. If two templates are the same, then at least their instantiations given template arguments will be the same.
template<template<class...> class LHS, template<class..> class RHS, class... S>
using is_same_template = std::is_same<LHS<S...>, RHS<S...>>::value;
Is there a way to compare LHS
and RHS
without S...
? I believe that without S...
, the comparator would have to be instantiated over S...
anyway. If they were template functions instead, I would not expect to be able to compare them, I would need to compare their instantiations. Is my intuition correct?
It looks like the same approach you might take with types or values works for templates. The first two lines show usage with just templates, and don't require the equals
or tag
functions, or any arguments to the supplied templates. The second two extract the templates from values and perform the same tests on those.
#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
}