home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 33,222 of 33,346   
   Daryle Walker to plash   
   Re: Why is the definition of a member fu   
   30 Sep 13 00:14:19   
   
   From: darylew@googlemail.com   
      
   [Got rejected once.]   
      
   On Wednesday, September 25, 2013 9:50:02 AM UTC-4, plash wrote:   
   > To avoid having to write an obscene number of definitions for each   
   > deriving class in this codebase, I have created an implementation   
   > stub as a class template and am defining the actual functions based   
   > on a type enum.   
   [SNIP]   
   > Here's an example of what I'm up to:   
   >   
   >     namespace A {   
   >         enum class Type : unsigned { SomeType, /*...*/ }   
   >   
   >         class Base { protected: virtual void f() = 0; /*...*/ };   
   >   
   >         template   
   >         class Impl final : public Base   
   >         { private: void f() override; /*...*/ };   
   >     } // namespace A   
   >   
   >     namespace B {   
   >         struct SomeTypeData { /* POD or standard-layout */ };   
   >   
   >         void A::Impl f() { /*...*/ }   
   >     } // namespace B   
      
   AFAIK, you can't specialize a method just for one version of a class   
   template.  You have to specialize (or partially specialize) the class   
   template and recreate the members, copying the definitions or altering   
   them as desired.  (You can even add, remove, or severely-alter members.   
   But as std::vector has shown, that will wreck havoc as far as   
   generic substitutability is concerned.)  Maybe a secret implementation   
   base class can help from repeating code.   
      
   * Remove that bad version of "f."   
   * After the "namespace B" block, make a new "namespace A" block.   
   * Declare a class template specialization of "Impl," with "SomeType"   
     and "SomeTypeData" as the parameters.  Derive from "Base" and   
     otherwise copy the original version of the template.  Alter that   
     version of "f" as you want.   
      
   There's probably a better solution, with more generality and   
   indirection, but I'll let someone else handle that.   
      
   ...   
      
   What about:   
      
       namespace A {   
           enum class Type : unsigned;   
      
           template < Type type, class Data >   
           struct f_action;   
      
           class Base   
           {   
           public:   
               void  call_f() { f(); }   
      
               virtual  ~Base() = default;   
      
           private:   
               virtual  void  f() = 0;   
           }   
      
           template < Type type, class Data >   
           class Impl final   
               : public Base   
           {   
           public:   
               Impl( Data d )  : m_data( std::move(d) )  {}   
      
           private:   
               Data  m_data;   
      
               void  f() override  { f_action{}( m_data ); }   
           }   
       }   
      
   And for each specialization, you do:   
      
       namespace A {   
           template <>   
           struct f_action   
           {   
               void  operator()( B::SomeTypeData /* & or && or neither */)   
               { /*Whatever*/ }   
           }   
       }   
      
   Hopefully, the definition of Impl::f won't need f_action to be   
   complete at that point.   
      
   Daryle W.   
      
      
   --   
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca