
Hi Dave, Thanks for your input. I had a few follow up questions and requests for clarifications below: On Thu, 2005-03-31 at 14:43 -0500, David Abrahams wrote:
Bruce Trask <Bruce.Trask@prismtech.com> writes:
Hi,
I coded up the mpl::map versus the SWITCH approach and I am thinking that the SWITCH approach is better in this case as it shows the various mnemonic choices at the point of the SWITCH. Thoughts?
You can't meaningfully compare the syntax of the map with something that has unspecified syntax (i.e. switch) ;-)
The syntax of the SWITCH I was referring to is the one on page 439 of Generative Programming. I.e. template<int tag, class Case> class SWITCH { typedef typename Case::Next NextCase; enum { caseTag = Case::tag, found = (caseTag == tag || caseTag ==DEFAULT) }; public: typedef typename IF<found, typename Case::Type, typename SWITCH<tag, NextCase>::RET>::RET RET; }; template<int tag> class SWITCH<tag, NilCase> { public: typedef NilCase RET; }; with the usage syntax of SWITCH<ti, CASE<one, First, CASE<two, Second, CASE<three, Third> > >
::RET::func();
Am I missing what you are saying here?
In MPL, the closest thing to switch is currently spelled:
eval_if< is_same<c1,x> , identity<r1> , eval_if< is_same<c2,x> , identity<r2> ...
, eval_if< is_same<cn,x> , identity<rn> , identity<default_> > >
Cool. Thanks.
Also if the SWITCH is the better way to go, it leads me to my original question as to whether there is a mpl::switch?
enum tagit { one, two, three };
struct First { static void func() { cout << "First" << endl; } };
struct Second { static void func() { cout << "Second" << endl; } };
struct Third { static void func() { cout << "Third" << endl; } };
typedef mpl::map< mpl::pair<mpl::integral_c<tagit, one>, First>, mpl::pair<mpl::integral_c<tagit, two>, Second>, mpl::pair<mpl::integral_c<tagit, three>, Third> > funcchooser;
Ehm, if that's all you need to do:
template <int> func_;
template <> struct func_<1> { static void func() { cout << "First" << endl }};
template <> struct func_<2> { static void func() { cout << "Second" << endl }};
template <> struct func_<3> { static void func() { cout << "Third" << endl }};
template<tagit ti> void funcCaller() { func_<ti>::func(); }
Right. Good point. My real code is a hair more complicated but even so, I guess this is the heart of my question and it stems from page 62 of C++ Template Metaprogramming section on Type Selection, where you and Aleksey talk about the alternative of using classes with mnemonic names versus ad hoc template specializations. So my question is, do you guys have a rule of thumb for going with ad hoc specializations versus using metafunctions with mnemonic names or is it just whether is reads better at the point of the call? I have attached the source for my running example. Thanks in advance, Bruce