I started playing with extern templates a bit and I came across a problem that I cannot find relevant information for. Say I have a class template with a non-template function (defined in the class template declaration). I declare some extern instance instances for the class, but how can I declare a friend function as extern too?
Here is a sample code:
// --- test.h --- template <typename T> class Foo { private: T value; public: friend void some_friend_function(Foo<T>& obj) { obj.value -= T(42); }; void some_member_function(T rhs) { value += rhs; }; }; extern template class Foo<int>; //extern void some_friend_function(Foo<int>&); // I tried this also... // --- test.cpp --- #include "test.h" template class Foo<int>; //void some_friend_function(Foo<int>&); // ... with this.
When I compile the above (with or without commented out lines), I get only the following exported character:
0000000000000000 W _ZN3FooIiE20some_member_functionEi
So, non-template functions definitely don't get an instance (and extern 'd) along with an explicit instance of the template template. This is normal? At least what GCC produces (tested on 4.6.3 and 4.7.2).
Is there a way to make a friend function mark extern? I know that this is not a huge problem, since I can happily live with friend functions that are created as needed (that is, without external ones), but I am curious to know if there is a way to do this, if not, it was supervision or intentional thing?
EDIT: obvious workarounds
My question is about non-template functions of friends, not finding a workaround to avoid the problem, which is trivial. The first obvious workaround is this:
template <typename T> class Foo { private: T value; public: template <typename U> friend void some_friend_function(Foo<U>& obj) { obj.value -= T(42); }; }; extern template class Foo<int>; extern template void some_friend_function(Foo<int>&);
And one more, more suitable, but more unpleasant, is this:
template <typename T> class Foo; // forward-declare. template <typename T> void some_friend_function(Foo<T>&); // declaration. template <typename T> class Foo { private: T value; public: friend void some_friend_function<>(Foo<T>& obj); // befriend the T-specialization. }; template <typename T> void some_friend_function(Foo<T>& obj) { // definition. obj.value -= T(42); }; extern template class Foo<int>; extern template void some_friend_function(Foo<int>&); // --- in cpp file: --- template class Foo<int>; template void some_friend_function(Foo<int>&);