TITLE: templ specialized member functions (Newsgroups: comp.lang.c++.moderated, 5 Jan 2000) ALEX: "Andrei Alexandrescu" [snip] Here's the problem: template class SmartPtr { public: ... private: void IncReference() { // single-threaded algorithm // just an increment ... } ... }; // Specialize for multithreaded smart pointers // Bright Idea (tm). Copyright (c) 1999, Léonard Génie // This function will be instantiated for multithreaded // SmartPtrs ONLY. Youpee! template class SmartPtr::IncReference() { // multithreaded algorithm CriticalSectionLock lock(..); ... } The code above doesn't work, and we need a workaround for it. Peter Dimov suggested traits, and Hyman Rosen suggested inheritance. Both have drawbacks that don't make them scaleable for either non-trivial manipulation or multiple template parameters. What we need is simply to specialize a member function of a class template, fixing only ONE of the template arguments that the class template takes. If we can do this, the sky's the limit (if you manage to go past the air conditioning installation and the ceiling). My solution follows. It works great, but it's a bit hard to explain. 1. You define a private template member function. It may have the same name as the member function that you need to partially specialize. In our case, the function is IncReference. You provide a single template parameter to the function - the one that you want fixed. In our case it's the bool multiThreaded. template class SmartPtr { public: ... private: // *** Code added begins template void IncReference(); template <> void IncReference(); { // single-threaded algorithm // just an increment ... } template <> void IncReference() { // multi-threaded algorithm CriticalSectionLock lock(..); ... } // *** Code added ends ... }; 2. You implement the function that you need to partially specialize to forward to the template function defined above, like so: template class SmartPtr { public: ... private: // *** Code modified begins void IncReference() { return this->template IncReference(); } // *** Code modified ends ... }; You can save yourself the "this->template" trouble if you give the two functions different names. Note how you pass the outer template argument to the inner function template. This is where effectively the magic happens. 3. That's it! Let's analyze the resulting situation. * You can use one specialization from within another (for instance, the multithreaded version of IncReference can lock the object, then call the single-threaded version) => a lot of code reuse with few functions. * The compiler will take into account only the functions that are actually used. * The idiom is acceptable in terms of artifacts/scaffolding - only the forwarding stuff. * The idiom scales nicely to multiple template parameters. You can combine the functions tuned for various template parameters, again getting a lot of reuse. It's a pity we have to pass through this workaround instead of having partial specialization of member functions in the first place. _______________________________________________ cpptips mailing list http://cpptips.hyperformix.com