Boost logo

Boost Users :

From: Bruce Trask (Bruce.Trask_at_[hidden])
Date: 2005-04-01 09:35:10


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_at_[hidden]> 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
>
>




Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net