Reputation: 676
So I need to find out if two templates are the same, even if the parameters are not, ie. if in T<A>
and U<B>
T and U are the same, even if A and B are not. std::is_same
can't be used, as it only regards the full type.
My first solution was this:
template<typename T, typename U>
struct is_same_template : std::false_type {};
template<template<typename> typename T, typename A, typename B>
struct is_same_template<T<A>, T<B>> : std::true_type {};
template<template<typename> typename T, typename A, template<typename> typename U, typename B>
struct is_same_template<T<A>, U<B>> : std::false_type {};
It works, but only for templates with one parameter, so I extended it to:
template<typename T, typename U>
struct is_same_template : std::false_type {};
template<template<typename...> typename T, typename... A, typename... B>
struct is_same_template<T<A...>, T<B...>> : std::true_type {};
template<template<typename...> typename T, typename... A, template<typename...> typename U, typename... B>
struct is_same_template<T<A...>, U<B...>> : std::false_type {};
That works great, even for templates with parameter packs.
Example:
template <typename... Params>
struct Test1 {};
template <typename... Params>
struct Test2 {};
struct Foo {};
struct Bar {};
int main(int argc, char** argv) {
std::cout << std::boolalpha;
std::cout << is_same_template<Test1<Foo>, Test2<Foo>>::value << '\n';
std::cout << is_same_template<Test1<Foo>, Test2<Bar>>::value << '\n';
std::cout << is_same_template<Test1<Foo, Bar>, Test2<Bar>>::value << '\n';
std::cout << is_same_template<Test1<Foo>, Test1<Foo>>::value << '\n';
std::cout << is_same_template<Test1<Foo>, Test1<Bar>>::value << '\n';
std::cout << is_same_template<Test1<Foo, Bar>, Test1<Bar>>::value << '\n';
return 0;
}
Output:
false
false
false
true
true
true
My problem is that in the actual use case I did this for the template parameter is an int parameter pack:
template <int... Indexes>
struct ArgIndexes {};
I didn't know that types and non-types are handled differently. When testing with ArgIndexes
the result was always the value of
template<typename T, typename U>
struct is_same_template : std::false_type {};
Is there any way to get this to work with both type and non-type parameter packs without handling every kind of non-type parameter pack specifically?
EDIT
I just realized that
template<template<typename...> typename T, typename... A, template<typename...> typename U, typename... B>
struct is_same_template<T<A...>, U<B...>> : std::false_type {};
is redundant and can be removed.
Upvotes: 8
Views: 274
Reputation: 676
So auto works. All my tests worked with this combination:
template<typename T, typename U>
struct is_same_template : std::false_type {};
template<template<typename...> typename T, typename... A, typename... B>
struct is_same_template<T<A...>, T<B...>> : std::true_type {};
template<template<auto...> typename T, auto... A, auto... B>
struct is_same_template<T<A...>, T<B...>> : std::true_type {};
I didn't test auto before because the Clang integrated into my IDE told me that auto is not allowed. Well, it is, and it works. Thanks @Jarod42 for making me reconsider it.
Upvotes: 2
Reputation: 63277
If you only want to check templates with a single pack of value parameters, you can add this specialization:
template<typename A, template<A...> typename T, A... X, A... Y>
struct is_same_template<T<X...>, T<Y...>> : std::true_type {};
Used like:
template <int... Params>
struct Test1 {};
template <char... Params>
struct Test2 {};
int main(int argc, char** argv) {
std::cout << std::boolalpha;
std::cout << is_same_template<Test1<1, 2, 3>, Test2<1, 2, 3>>::value << '\n';
std::cout << is_same_template<Test1<1>, Test2<2>>::value << '\n';
std::cout << is_same_template<Test1<1, 2>, Test2<2>>::value << '\n';
std::cout << is_same_template<Test1<1>, Test1<1>>::value << '\n';
std::cout << is_same_template<Test1<1>, Test1<2>>::value << '\n';
std::cout << is_same_template<Test1<1, 2>, Test1<2>>::value << '\n';
return 0;
}
Upvotes: 1