When compiling this snipet in godbolt, most compilers generate two different get methods (different symbol in the assembly window):
template<typename T>
struct Field { T impl; };
template<typename T>
using CurrentField = Field<T>;
template<template <typename> class F>
struct Encompassing { F<int> member; };
auto get(Encompassing<Field> const& instance)
{
return instance.member.impl;
}
auto get(Encompassing<CurrentField> const& instance)
{
return instance.member.impl;
}
I see CurrentField in symbols even if it is an alias. Only gcc complains about redefinition (as expected).
C++ reference on type_alias says
It does not introduce a new type
so I think it is not supposed to behave like this, am I wrong?
Actually most compiler seems to behave like the alias template was substituted with a class Trait like
template<typename T>
struct CurrentField
{
alias type = Field<T> ;
};
Edit:
Here is a more representative example of What I try to achieve on Godbolt. Note that it compiles since there is a single source and no linking but the msvc assembly shows it generated both the pre-instantiated signatures and user calls signatures.
There are 4 parts:
1. a container library with multiple kind of templates like StackField and HeapField,
2. an utility library with member methods like size, with the field as template argument (like the second workaround you proposed),
3. implementations are hidden and pre-instantiated in the c++ for different fields
4. users link their application A and B against this library, using aliases like AField and BField. It works with gcc but link fails in msvc because the signature of my pre-instantiated implementations and the users calls don't match