How to make template function friend of template c

2019-05-31 22:58发布

问题:

I have a template class with private constructor and destructor:

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>(...);
}

I'm not sure of the correct syntax for the friend. Can anybody help?

回答1:

Ignoring the ellipses (which I assume mean "a bunch of parameters that aren't relevant to the question"), this should work:

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() 
{
      /* ... */
}

Notice that the friend declaration is essentially the same as the function declaration but with the friend keyword prefixed before the return type.

Also, the destructor is public so that users of initialize() will be able to destruct the returned instance of Client<>. The constructor is still private so only initialize() can create instances of it.

The above code should allow this to work:

int main()
{
    Client<int> client = initialize<int>();
}


回答2:

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


回答3:

It depends on what exactly you are trying to achieve. You may want to befriend a single instantiation of the template, or you might want to befriend all instantiations. Finally you might not really want to befriend a template, but just a non-templated function that is automatically generated by the compiler upon instantiation of your class template...

Befriending the whole template:

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

Befriending a concrete instantiation (i.e. allowing f<int> access to MyClass<int> but not to 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() { ... }

Automatic instantiation of a befriended non-template function:

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

I would recommend that you use the latter, unless the function is parametrized with other template parameters than the T for MyClass<T>.

Recommend reading: overloading friend operator<< for template class



回答4:

You should probably make your destructor public. If you need to keep it private you need to declare another friend function to delete the Client objects that you've created.

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;
}