From: alf.p.steinbach+usenet@googlemail.com   
      
   On 15.01.2014 01:47, Ryan wrote:   
   > I've included the below code in what I believe is the hard way of doing   
   > things. Structure A has the information on the structure type being   
   > stored. It could be either a C, D or E structure.   
      
   I assume that means that an "A" object stores an object that can be   
   either a C, a D or an E.   
      
      
   > If you notice the   
   > switch statement, though, I really don't care what type it being   
   > returned. They all use the same add method. Is there a way 'getType'   
   > can return a type for tag dispatching that would allow the getC, getD   
   > and getE to become a templated method based on a type trait?   
      
   It's easy enough to generalize getC(), getD() and getD() as a single   
   member function template, using e.g. dynamic_cast.   
      
   A getType function is not needed for that, nor is some type traits class   
   needed.   
      
   I assume that it's OK to just get the function template even if it   
   doesn't involve getType or some type trait.   
      
      
   > This way   
   > the switch statement can be eliminated and the simple 'add' called.   
      
   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.   
      
      
   > #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;   
   > }   
      
      
   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.   
      
      
   [code]   
   #ifndef CPPX_IS_DELETED   
   # define CPPX_IS_DELETED = delete   
   #endif   
      
   #include    
   #include // std::unique_ptr   
   #include // std::move   
   using namespace std;   
      
   struct B {};   
      
   struct Stored_object   
   {   
    virtual void add( B ) = 0;   
   };   
      
   struct C: Stored_object   
   {   
    void add( B ) override { cout << "Added C" << endl; }   
   };   
      
   struct D: Stored_object   
   {   
    void add( B ) override { cout << "Added D" << endl; }   
   };   
      
   struct E: Stored_object   
   {   
    void add( B ) override { cout << "Added E" << endl; }   
   };   
      
   class A   
   {   
   private:   
    unique_ptr stored_object_;   
      
    A( A const& ) CPPX_IS_DELETED;   
    A& operator=( A const& ) CPPX_IS_DELETED;   
      
   public:   
    auto stored_object()   
    -> Stored_object&   
    { return *stored_object_; }   
      
    template< class Stored >   
    auto stored()   
    -> Stored&   
    { return dynamic_cast( *stored_object_ ); }   
      
    A( C o ): stored_object_( new C( move( o ) ) ) {}   
    A( D o ): stored_object_( new D( move( o ) ) ) {}   
    A( E o ): stored_object_( new E( move( o ) ) ) {}   
   };   
      
   auto main()   
    -> int   
   {   
    C c;   
    A a( c );   
      
      
    a.stored_object().add( B() );   
      
    (void) a.stored(); // Does not throw.   
    cout << "Attempting to access stored object as a `D`..." << endl;   
    try   
    {   
    a.stored(); // Throws! As it should.   
    }   
    catch( exception const& x )   
    {   
    cerr << "! " << x.what() << endl;   
    }   
   }   
   [/code]   
      
      
   If you want A::stored to return a copy, or reference to const, just   
   modify the result type (and in the latter case possibly make also the   
   member function const).   
      
      
   Cheers & hth.,   
      
   - Alf   
      
   PS:   
   Norwegian/Scandinavian readers: I'm looking for a job since I'm now   
   almost recovered from surgery over the last year and a half (just a   
   little bit more surgery now at the end of the month) . Pro hiring me:   
   I'm pretty good. Con: age. I'm a moderator of this group, and I was   
   awarded Microsoft MVP in 2012. Your firm just may be able to catch me.   
      
      
   --   
    [ 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)   
|