Как сделать функцию шаблона другом класса шаблона - PullRequest
1 голос
/ 25 июля 2011

У меня есть шаблон класса с приватным конструктором и деструктором:

template <typename T>
class Client
{
    private:
        Client(...) {}
        ~Client()   {}

        template <typename U>
        friend class Client<T>& initialize(...);
};


template <typename T>
Client<T> initialize(...) 
{
      Client<T> client = new Client<T>(...);
}

Я не уверен в правильном синтаксисе для друга. Кто-нибудь может помочь?

Ответы [ 4 ]

4 голосов
/ 25 июля 2011

Игнорирование эллипсов (которые, как я предполагаю, означает «набор параметров, не относящихся к вопросу»), это должно работать:

template <typename T>
class Client
{
private:
    Client() {} // Note private constructor
public:
    ~Client() {} // Note public destructor

    // Note friend template function syntax
    template<typename U>
    friend Client<U> initialize();
};


template<typename T>
Client<T> initialize() 
{
      /* ... */
}

Обратите внимание, что объявление друга по сути совпадает с объявлением функции, но с ключевым словом friend перед префиксом возвращаемого типа.

Кроме того, деструктор является общедоступным, так что пользователи initialize() смогут уничтожить возвращенный экземпляр Client<>. Конструктор все еще является закрытым, поэтому только initialize() может создавать его экземпляры.

Приведенный выше код должен позволить этому работать:

int main()
{
    Client<int> client = initialize<int>();
}
1 голос
/ 25 июля 2011

Это зависит от того, что именно вы пытаетесь достичь.Вы можете подружиться с одним экземпляром шаблона или подружиться с всеми экземплярами.Наконец, вы, возможно, на самом деле не хотите подружиться с шаблоном, а просто с не шаблонной функцией, которая автоматически генерируется компилятором при создании экземпляра шаблона вашего класса ...

Поддержка всего шаблона:

template <typename T>
class MyClass {
   template <typename U>
   friend MyClass<U> f();
};

Поддержка конкретного экземпляра (т. Е. Предоставление f<int> доступа к MyClass<int>, но не к MyClass<double>):

// Forward declarations
template <typename T>
class MyClass;
template <typename T>
MyClass<T> f();

// Definition of class template
template <typename T>
class MyClass {
   friend MyClass<T> f<T>();
};

// Definition of friend function
template <typename T>
MyClass<T> f() { ... }

Автоматическое создание экземпляра дружественной не шаблонной функции:

template <typename T>
class MyClass {
    friend MyClass<T> f() { ... } // define inline
};

Я бы порекомендовал вам использовать последнее, если только функция не параметризована с другими параметрами шаблона, чем T для MyClass<T>.

Рекомендуем прочитать: перегрузка оператора друга << для класса шаблона </a>

1 голос
/ 25 июля 2011
template <typename U> friend Client<U> initialize(.....);
0 голосов
/ 25 июля 2011

Вы, вероятно, должны сделать свой деструктор public.Если вам нужно сохранить private, вам нужно объявить другую функцию friend для удаления созданных вами Client объектов.

template <typename T>
class Client
{
    private:
        Client() {}
        ~Client() {}

        template <typename U>
        friend Client<U> *initialize();

        template <typename U>
        friend void destroy( Client<U> * );
};


template <typename T>
Client<T> *initialize() 
{
  return new Client<T>();
}

template <typename T>
void destroy( Client<T> *client )
{
  delete client;
}

int main()
{
  auto client = initialize<int>();

  destroy( client );

  return 0;
}
...