Идентификация псевдонимов шаблонов

Рассмотрим набор шаблонных псевдонимов:

template<class T> using foo = T*;
template<class T> using bar = T*;
template<class T> using buz = foo<T>;

template< template<class>class TT > struct id {};

using id_foo = id<foo>;
using id_bar = id<bar>;
using id_buz = id<buz>;

Являются ли id_foo, id_bar, id_buz одинаковыми или разными типами? Существуют ли foo, bar, buz одинаковые или разные шаблоны?

У разных компиляторов есть разные мнения по этому поводу. В частности,

  • MSVC 2015 и clang 3.5 считают, что все они разные.
  • gcc 4.9 рассматривает buz так же, как foo

Стандартный С++ 11 в главе 14.5.7 "Шаблоны псевдонимов" неясно.

Ответ 1

Как TC указал в свой комментарий на вопрос, это известное отверстие стандарта.

Текущая редакция 14.5.7 [temp.alias] касается только эквивалентности специализации шаблона псевдонима с идентификатором типа после подстановки. Должна быть добавлена ​​формулировка, указывающая, при каких обстоятельствах сам шаблон псевдонима эквивалентен шаблону класса.

То есть: любая специализация foo, bar и buz будет представлять один и тот же тип. Но нет гарантии, что при использовании в качестве параметра шаблона foo, bar и buz взаимозаменяемы.