Подтвердить что ты не робот

Подружиться с параметром шаблона шаблона

У меня есть шаблон шаблона с параметром шаблона шаблона, и я хочу объявить этот параметр (то есть все его специализации) как friend. Но я не могу найти правильный синтаксис.

template <template <class> class T>
struct Foo {

    template <class U>
    friend T;           // "C++ requires a type specifier for all declarations"

    template <class U>
    friend struct T;    // "declaration of 'T' shadows template parameter"

    template <class U>
    friend struct T<U>; // "cannot specialize a template template parameter"

    pretty<please>
    lets(be) friends T; // Compiler shook its standard output in pity
};

Как я могу объявить параметр шаблона шаблона как friend?

фрагмент Coliru

4b9b3361

Ответ 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;
};

Из-за одного уровня косвенности здесь нет никакого теневого и повторного использования, и эта ситуация описывается следующим образом:

cppreference:

Оба шаблона шаблона шаблона и объявления шаблона класса могут отображаться с помощью спецификатора friend в любом нелокальном классе или шаблоне класса (...). В этом случае каждая специализация шаблона становится другом, независимо от того, является ли она неявно созданной, частично специализированной или явно специализированной. Пример: class A { template<typename> friend class B; }

Однако, похоже, что clang и MSVC думают иначе: см. coliru или godbolt. Более того, их сообщения об ошибках кажутся бессмысленными, поэтому он выглядит как ошибка компилятора (или просто некорректная ошибка синтаксиса). GCC компилирует и исполняет упомянутые фрагменты отлично, но я до сих пор не уверен, что это правильное решение.

Ответ 2

Шаблоны, как правило, заставляют программистов слишком усложнять ситуацию. Я не совсем уверен, что вы пытаетесь сделать, и я подозреваю, что, вероятно, лучший способ это сделать, но это должно сработать.

template <template <class> class T, class U>
class Foo {
    friend class T<U>;
};