Ответ 1
Я нашел, что эта проблема очень интересна для исследования. Согласно стандарту (С++ 11 и выше) это должно работать нормально, я думаю:
template <template <class> class U>
struct identity {
template <typename T>
using type = U<T>;
};
template <template <class> class U>
struct Foo {
template <typename>
friend class identity<U>::type;
};
Из-за одного уровня косвенности здесь нет никакого теневого и повторного использования, и эта ситуация описывается следующим образом:
Оба шаблона шаблона шаблона и объявления шаблона класса могут отображаться с помощью спецификатора friend в любом нелокальном классе или шаблоне класса (...). В этом случае каждая специализация шаблона становится другом, независимо от того, является ли она неявно созданной, частично специализированной или явно специализированной. Пример:
class A { template<typename> friend class B; }
Однако, похоже, что clang и MSVC думают иначе: см. coliru или godbolt. Более того, их сообщения об ошибках кажутся бессмысленными, поэтому он выглядит как ошибка компилятора (или просто некорректная ошибка синтаксиса). GCC компилирует и исполняет упомянутые фрагменты отлично, но я до сих пор не уверен, что это правильное решение.