External class templates and non-template functions

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>&); // --- in cpp file: --- template class Foo<int>; 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>&); 
+4
source share
1 answer

The effect of the “extern template class” is to declare an explicit instance. The effect of explicit declaration of instantiation does not apply to built-in functions or specialized templates (14.7.2 [temp.explicit], clause 10):

With the exception of built-in functions and specialized template templates, explicit declarations of instantiation affect the suppression of the implicit instance of the object to which they refer.

Since the definition of the friend function in the class definition is necessarily an inline function, it will remain an inline function that does not depend on an explicit declaration of template creation (and, as you correctly noted, this isn’t a template and does not comply with the rules for creating template templates).

0
source

Source: https://habr.com/ru/post/1439589/


All Articles