Class Template Friend Functions

I have a class template Foo<T> .

I would like to implement a non-member Bar function that takes two Foo and returns a Foo . I want Bar be non-member, because for subscribers it is more natural to write Bar(f1, f2) than f1.Bar(f2) . I also want Bar be inline , because the calculation is trivial and frequent.

 template <typename T> inline Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs) { ... } 

The stunt Bar needs access to Foo private data. I would prefer not to have access to private data - there is no reason to publish personal data for users. Therefore, I would like to make Bar friend of Foo .

 template <typename T> class Foo { ... private: T w, x, y, z; friend Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs); }; 

Here, where I run into trouble. The compiler complains:

The built-in specifier cannot be used when a friend declaration refers to the specialization of a function template.

Is this rule an introduced standard or is it specific to MSVC ++?

Here is what I tried:

  • Make Bar a public member function const, and then declare a non-member version that just returns lhs.Bar(rhs) . This seems like the least hacky solution.

  • Remove the inline hint, knowing that the compiler will solve the embedding issue regardless of the hint. Does this mean that it contradicts the rule of one definition? It still needs to be defined in the header file because it is a function template.

  • Declare a member function with a template type dummy:

     template <typename T> class Foo { ... private: T w, x, y, z; // Note that this declaration doesn't actually use Dummy. It just there to // satisfy the compiler. template <typename Dummy> friend Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs); }; 

I'm not quite sure why this works, but it suits the compiler.

Is there a better solution?

+8
c ++ friend function-templates
source share
3 answers

If the calculation is trivial, I would write:

 template <typename T> class Foo { ... private: T w, x, y, z; public: friend Foo Bar(const Foo &lhs, const Foo &rhs) { ... } }; 

This does not weaken ODR - it is a built-in function with external communication (3.2 / 5 excludes this from ODR, provided that the definitions are identical, 7.1.2 / 3 says that it is built-in).

However, this does not define the Bar<T> function template, it simply defines a set of function overloads for Bar . Perhaps there is some reason not ascertained in the question, this means that this will not work for you, because you really need a template.

+5
source share

I like option 1 best:

 template <typename T> inline Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs) { return lhs.Bar(rhs); } template <typename T> class Foo { ... Foo<T> Bar(const Foo<T> &other) const; private: T w, x, y, z; }; 

Then the functionality is safely contained within the class, but for convenience you provide a wrapper function.

+2
source share

Bar is a template, so it should also be a template in a friend’s declaration.

You do not have to use a dummy parameter, but you can most likely use

  template <typename U> friend Foo<U> Bar(const Foo<U> &lhs, const Foo<U> &rhs); 

You cannot use T as a template parameter here, since there is already an external T in the region.

+1
source share

All Articles