I have a class template Foo<T>
.
I'd like to implement a non-member function Bar
that takes two Foo
s and returns a Foo
. I want Bar
to be a non-member because it will be more natural for callers to write Bar(f1, f2)
than f1.Bar(f2)
. I also want Bar
to 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 trick is Bar
needs access to Foo
's private data. I'd prefer not to have accessors to the private data--there's no good reason to expose the private data to users. So I'd like to make Bar
a 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's where I run into trouble. The compiler complains:
The inline specifier cannot be used when a friend declaration refers to a specialization of a function template.
Is this rule imposed by the standard or is it specific to MSVC++?
Here's what I've tried:
Make
Bar
a const public member function, and then to declare a non-member version that simply returnslhs.Bar(rhs)
. This seems the least hacky solution.Remove the
inline
hint, knowing that the compiler is going to decide about inlining regardless of the hint. Does this then run afoul of the one-definition rule? It will still have to be defined in a header file because it's a function template.Declare the member function with a dummy template type:
template <typename T> class Foo { ... private: T w, x, y, z; // Note that this declaration doesn't actually use Dummy. It's just there to // satisfy the compiler. template <typename Dummy> friend Foo<T> Bar(const Foo<T> &lhs, const Foo<T> &rhs); };
I'm not entirely sure why that works, but it does satisfy the compiler.
Is there a better solution?