As I was playing around I stumbled over the following code snippet, which surprisingly doesn't match my expectations.
#include <tuple>
#include <type_traits>
template <class... Ts>
using myTuple = std::tuple<Ts...>;
template <template <class...> class Lhs, template <class...> class Rhs>
struct is_same
: public std::false_type
{};
template <template <class...> class T>
struct is_same<T, T>
: public std::true_type
{};
int main() {
static_assert(is_same<myTuple, std::tuple>::value, "not same");
}
I droped it on godbolt and tried to compile it with 3 different compilers (clang, msvc and gcc) and received mixed results.
clang:
<source>:18:5: error: static_assert failed due to requirement 'is_same<myTuple, std::tuple>::value' "not same"
static_assert(is_same<myTuple, std::tuple>::value, "not same");
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MSVC:
<source>(18): error C2338: static_assert failed: 'not same'
gcc:
(no errors)
Now I'm questioning myself, which one is the correct behaviour? I would expect that both arguments are the same and therefore the specialization is used, because aliases usually don't differ from the original type. If that's not the correct argument here, I would like to know why.
GCC is wrong about this and Clang and MSVC are correct. The static_assert
should fail.
myTuple
is not an alias for the template std::tuple
. There are no aliases for templates, only for types.
std::tuple
and myTuple
are two distinct templates, one a class template and the other an alias template. Alias template are not called that because they alias other templates. They are called that
because every specialization of an alias template is a (type) alias.
That each specialization of the two templates with the same list of template arguments happen to result in something referring to the same type shouldn't be relevant here.
Deduction on the true
overload should fail for deducing two different values (i.e. templates) for T
.
But see e.g. the open (but old) CWG issue 1286 which considers making certain alias templates of the form you are using equivalent to the class template used in its definition. I guess this should then also affect template argument deduction to consider the two values deduced for T
"consistent". The issue also links to the resolved CWG issue 1244 which confirms that the alias and class template are not equivalent and so (I would say) also not "consistent" for the purpose of template argument deduction.