Ответ 1
1 Объявление шаблона, в котором объявление является декларацией псевдонимов (Раздел 7) объявляет идентификатор шаблоном псевдонимов. Псевдоним template - это имя для семейства типов. Имя псевдонима template - это имя шаблона.
2 Когда идентификатор шаблона ссылается на специализацию псевдонима шаблон, он эквивалентен ассоциированному типу, полученному подстановка его шаблонных аргументов для параметров шаблона в идентификаторе типа шаблона псевдонима.
В вашем примере Foo
и Pack<Foo>::Container
(нет списка параметров) являются именами шаблонов, которые не представляют тип, а только шаблон. Например, Foo<int>
и Pack<Foo>::Container<int>
будут идентификаторами шаблонов и поэтому будут эквивалентны.
Насколько я знаю, стандарт не указывает никакого отношения эквивалентности между именами шаблонов, поэтому MSVC и Clang имеют право предположить, что эквивалентны только идентичные имена шаблонов.
Но вы все же можете специализироваться или перегружать на основе идентификатора шаблона, если этого достаточно для конкретного случая использования. например:.
template< typename C >
struct IsFoo : std::false_type
{
};
template<class T>
struct IsFoo<Foo<T>> : std::true_type
{
};
static_assert( IsFoo<Foo<int>>::value, "Only foos!" );
static_assert( IsFoo< Pack<Foo>::Container<int> >::value, "Only foos!" );
static_assert( IsFoo< Pack<Bar>::Container<int> >::value == false, "Not a foo!" );
или
template<class T>
void do_stuff(const T&) {}
template<class T>
void do_stuff(const Foo<T>&) {}