Re: Possible Tag Dispatching
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 <iostream>
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 <iostream>
#include <memory> // std::unique_ptr
#include <utility> // 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> 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&>( *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<C>(); // Does not throw.
cout << "Attempting to access stored object as a `D`..." << endl;
try
{
a.stored<D>(); // 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! ]