The context
This question asked if it is possible to write a trait that can retrieve the template from a given instantiation. In a nutshell the question was: "Is it possible to write a f
such that f<foo<int>>::type
is foo
?"
This answer presents something that I would have expected to be exactly what that question asked for, but the answer already mentions that it is "not exactly" what has been asked for.
The code
To see the code in action and understand why it was labeled as "not exactly" I wrote this:
#include <type_traits>
#include <iostream>
// the template
template <typename T> struct foo {};
// not the template
template <typename T> struct not_foo {};
template <template<class> class A, template<class> class B>
struct is_same_template : std::false_type {};
// this is the questionable part
template <template<class> class A>
struct is_same_template<A,A> : std::true_type {};
// copied from said answer
template <typename T> struct template_class;
template <template <typename> class C, typename T>
struct template_class<C<T>>
{
template <typename U>
using type = C<U>;
};
// what will we get?
int main (){
std::cout << is_same_template<foo,foo>::value;
std::cout << is_same_template<foo,not_foo>::value;
std::cout << is_same_template<foo, template_class<foo<int>>::type>::value;
}
The output
What I was expecting, gcc:
101
My surprise, clang:
100
The question
Who is right here? Gcc, because template_class< foo<int> >::type
is foo
? Or clang, becaue comparing two different templates for equality doesn't make much sense?
If the outcome is implementation defined, or undefined, then what exactly in the code is undefined / implementation defined?
PS
At first I was expecting the outcome of gcc with no doubts, but in the meantime I was convinced that my expectations were not quite founded, hence this question.