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,274 of 33,346   
   Alf P. Steinbach to Ryan   
   Re: Possible Tag Dispatching (1/2)   
   17 Jan 14 00:05:43   
   
   From: alf.p.steinbach+usenet@googlemail.com   
      
   On 16.01.2014 07:49, Ryan wrote:   
   > On Wednesday, January 15, 2014 5:02:56 AM UTC-8, Alf P. Steinbach wrote:   
   >> On 15.01.2014 01:47, Ryan wrote:   
   >>   
   >> I assume that means that an "A" object stores an object that can be   
   >> either a C, a D or an E.   
   >   
   > It actually stores quite a few of them that were read in from a   
   > configuration file.   
      
   Well, your original code does not support access to a collection of   
   objects in each A instance, just a single stored object.   
      
   However, unless the stored objects are all of the same type, or some   
   other very predictable pattern, then nothing much of real importance is   
   changed.   
      
   Instead of a single object of unknown type we're simply dealing with a   
   collection of such, and putting things in a collection is mostly *an   
   orthogonal issue*. The C++ standard library has a number of containers   
   that you can use depending on the collection requirements. E.g.,   
   std::vector, std::set, std::dequeue, std::map, etc.   
      
     * * *   
      
   That said, it sounds like you would be better off using boost::variant   
   or something like that, rather than re-inventing the wheel.   
      
     * * *   
      
   However, /that/ said, let's proceed to reinvent the wheel, since that's   
   much of what this group is about: creating things and understanding   
   things, not just being pointed to relevant cans of food to heat.   
      
      
   >> A getType function is not needed for that, nor is some type traits class   
   >> needed.   
   >   
   > Since I don't know what types 'A' stores then I need something from 'A'   
   > to tell me the type to retrieve.   
      
   As the example code I posted illustrated (by way of just working   
   nicely), you do not need such extra information when you can assume that   
   the types are polymorphic.   
      
   For example, with polymorphic types you can use type-specific values by   
   associating them with the type at hand, via the C++ built-in `typeid`.   
      
   However, for this discussion I'll assume the worst, namely that you're   
   dealing with non-polymorphic classes that you don't control.   
      
      
   >> I assume that you want the ability to call a general `add` function, and   
   >> have it routed to or applied with the stored object of unknown type.   
   >   
   > True.   
      
   Great! :-)   
      
      
   >> Hopefully the following captures your requirements, but it's not clear   
   >> what aspects of the original code are requirements and what aspects are   
   >> simply artifacts of a particular attempt to implement the requirements.   
   >   
   > After seeing your suggestion let me clarify a few items.   
   >   
   > Structures B, C, D and E are all separate and can't be modified.  They   
   > don't share a common base class.   
   >   
   > The 'add' methods are really part of a class that also can't be modified.   
   >   
   > struct G {   
   >     void add(int num, B b, C c) { std::cout << "Added C" << std::endl; }   
   >     void add(int num, B b, D d) { std::cout << "Added D" << std::endl; }   
   >     void add(int num, B b, E e) { std::cout << "Added E" << std::endl; }   
   > };   
   >   
   > The only class I have control over is the 'A' class.   
   >   
   >>           a.stored();      // Throws! As it should.   
   >   
   > This is a problem.  I don't know that I want a 'D' type.  This is   
   > specified from the 'A' class.   
      
   Such getters for the stored object was specified by your original code,   
   where you expressed a desire to have the type-specific getters replaced   
   by a single function template, such as the above.   
      
      
   > a.stored();   
      
   The a.getType() call /can not/, even in principle, provide compile time   
   information about the dynamically stored object. That would require a   
   time machine. Such a time machine is rumored to exist for Python   
   (Guido's secret[1]), but AFAIK there is no such for C++ (although Bjarne   
   has sometimes been suspected of having changed the past so that the only   
   remnant of 1984 is the "++" in "C++").   
      
   However, let's look at the original code again, now with the added   
   information that   
      
   (1) there can be more than one stored object,   
      
   (2) only class A is open for modification,   
      
   (3) the classes can not, apparently, be assumed to be polymorphic,   
      
   (4) the `add` functions are really non-static members of a class G, so   
   that an instance of class G is required for the calls, and   
      
   (5) a /manifest/ way to obtain type identification is required, not just   
   support that with e.g. application of typeid would yield such id.   
      
      
   > #include    
   > enum eType { cc, dd, ee };   
   >   
   > struct B {};   
   > struct C {};   
   > struct D {};   
   > struct E {};   
   >   
   > struct A {   
   >    eType getType(void) { return dd; }   
   >    C getC(void) { return C(); }   
   >    D getD(void) { return D(); }   
   >    E getE(void) { return E(); }   
   > };   
   > void add(int num, B b, C c) { std::cout << "Added C" << std::endl; }   
   > void add(int num, B b, D d) { std::cout << "Added D" << std::endl; }   
   > void add(int num, B b, E e) { std::cout << "Added E" << std::endl; }   
   >   
   > int main() {   
   >    A a;   
   >    switch(a.getType()) {   
   >      case cc: add(3, B(), a.getC());  break;   
   >      case dd: add(4, B(), a.getD());  break;   
   >      case ee: add(5, B(), a.getE());  break;   
   >      default:   
   >        std::cout << "Problem" << std::endl;   
   >        break;   
   >    }   
   >   
   >    return 0;   
   > }   
      
      
   [code]   
   #ifndef CPPX_IS_DELETED   
   #   define CPPX_IS_DELETED  = delete   
   #endif   
      
   #include    
   #include    
   #include            // std::unique_ptr   
   #include         // std::exception   
   #include         // std::type_index   
   #include       // std::decay   
   #include           // std::move   
   #include    
   using namespace std;   
      
   struct B {};   
   struct C {};   
   struct D {};   
   struct E {};   
      
   struct G   
   {   
      void add( int n, B, C ) { cout << "Added C+" << n << endl; }   
      void add( int n, B, D ) { cout << "Added D+" << n << endl; }   
      void add( int n, B, E ) { cout << "Added E+" << n << endl; }   
   };   
      
   namespace stored {   
       struct Object   
       {   
           virtual void add( int, B, G& ) = 0;   
           virtual auto type_id() const -> type_index = 0;   
       };   
      
       template< class C_D_or_E_ >   
       struct Stored_part_   
           : Object   
           , C_D_or_E_   
       {   
           void add( int n, B b, G& g ) override { g.add( n, b, *this ); }   
      
           auto type_id() const   
               -> type_index   
               override   
           { return typeid( C_D_or_E_ ); }   
      
           Stored_part_( C_D_or_E_&& other ): C_D_or_E_( move( other ) ) {}   
       };   
   }  // namespace stored   
      
   template< class Type >   
   auto type_id()   
       -> type_index   
   { return typeid( Type ); }   
      
   auto const  id_c    = type_id();   
   auto const  id_d    = type_id();   
   auto const  id_e    = type_id();   
      
   class Variant   
   {   
   private:   
      
   [continued in next message]   
      
   --- 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