Boost logo

Boost Users :

From: David Abrahams (dave_at_[hidden])
Date: 2006-02-28 08:48:07


"Andy Little" <andy_at_[hidden]> writes:

> The expectation ( based on OP's light reading of examples I guess ) is this
>
> assert( boost::is_same <
> mpl::transform<
> vector_c<int,1,2,3> ,vector_c<int,1,1,1> ,some_plus_func
> > ::type ,
> vector_c<int,2,3,4>
> >::value == true);
>
> Personally I think ( even ) that is with (some mods) a realistic
> expectation.

If you think so, then please provide a patch that satisfies that
expectation. This is hard to accomplish in any reasonable amount of
code. Your patch should also satisfy

   assert( boost::is_same <
      mpl::transform<
          list_c<int,1,2,3> ,list_c<int,1,1,1> ,some_plus_func
> ::type ,
      list_c<int,2,3,4>
>::value == true);

(which is arguably even harder to do), just to prove that the
expectation can be handled over a range of sequence types.

> The above would make sense if vector_c was a standalone type rather than an
> *interface* to vector.

It would only make sense if it were reasonably implementable. The
above isn't even true for vector. That is,

   assert( boost::is_same <
      mpl::transform<
          vector<int,long> ,vector<char,char> , _1
> ::type ,
      vector<int,long>
>::value == true);

will likely also fail. The actual resulting type is something like

     vector2<int,long>

Totally apart from impelementation difficulty, there are some very
simple constraints that absolutely force this expectation to break
down in some cases. Consider

  push_back<list<a,b,c,...>, int>::type

list has a fixed number of template parameters (all with defaults).
At some point there is no longer a way to represent the sequence with
one more element as a specialization of list, and you're stuck.

> The act of doing that would introduce complexities sure because it
> would be necessary to specify the semantics. To make the above work
> some_plus_func would presumably need to look like
>
> template <int A,int B>
> some_plus_func;
>
> or
>
> template <typename T,T A,T B>
> some_plus_func;

No it would not. And that's for all practical purposes
unimplementable within the framework of the MPL. If you want a
library whose metafunctions can operate directly on integral
constants, and where you pass templates instead of types to
algorithms, you want a different library. See Loki, maybe.

> I think its possible to specialise transform to pick this up.

No it isn't. The 3rd argument to transform is a type; you can never
pass a template there, no matter how many specializations you write.

> Instead of the type placeholders you would use arbitrary constants (
> <0,0> )here:
>
> assert( boost::is_same <
> mpl::transform<
> vector_c<int,1,2,3> ,vector_c<int,1,1,1> ,some_plus_func<0,0>
> > ::type ,
> vector_c<int,2,3,4>
> >::value == true);

Well, that's something different altogether than what you said before.
Now you're passing a type again. But what you've written above not
only causes a code explosion in the metaprogramming library, it's
completely counter to the MPL aesthetic and philosophy. Maybe you
want a different library.

> Of course If vector_c was a standalone type then a function e.g 'to_vector' to
> convert to a mpl::vector would be required to get the current behaviour
>
> assert(boost::is_same<
> mpl::to_vector< long_<1>,vector_c<int,1,2,3,4> >::type,
> mpl::vector<long_<1>,long_<2>,long_<3>, long_<4> >
>>::value == true);
>
> Anyway the point is I dont think its impossible to come up with an alternative
> design as you seem to be suggesting.

Stop. I never suggested it was impossible to come up with an
alternative design. I have said, repeatedly, that meeting the
expectation you're describing here in any way results in a vast
expansion of the amount of code in the library, which would likely
cause slowdowns in user code, and is very difficult to do at all, to
say nothing of doing it well.

> But (Maybe more realistically) the same issues crops up with mpl::int_
>
> assert( boost::is_same <
> mpl::plus<
> int_<1>, int_<1>
> > ::type ,
> int_<2>
> >::value == true);
>
> Again I think thats a reasonable expectation, but it fails

That's a separate issue. It's far less hard to accomplish than what
you described above.

> But in both cases the mpl designers argument is that these are only
> interfaces, designed to save a bit of typing.

That's not an argument, it's a fact of the design intention.

> My problem with this argument is that (as it stands) they are an
> input only interface and so when the type is regurgitated as error
> messages or when using comparisons etc one is presented with
> something "conceptually identical" as far as the designers are
> concerned but that has been the result of what seem to the user like
> arbitary transformations. Thats not pleasant. To the uninitiated it
> just looks like somethings gone wrong with the calculation.

So submit a patch that fixes it. Surely you could have done so by
now, more easily than all of this posting. That would at least prove
your point that it's achievable.

> In case of int_, long_ etc ( and vector_c for that matter) the ideal
> would be for the above assertion to hold. int_'s and long_'s should
> be standalone types which have their own semantics. I think its not
> too difficult to add rules for how they interact with integral_c as
> well.

Go for it.

> As it stands mpl::plus assumes everythings an integral constant
> and perversely it actually reinforces that in code by giving back an
> integral_c whatever the actual integral_constant inputs are.

Whether that's perverse or not is obviously a matter of opinion.

> This as well as seeming arbitrary, makes int_'s and long_'s and
> vector_c basically superfluous IMO.

They're not superfluous: they save loads of typing. I would hate to
do without them.

> The current definition of mpl::plus (et al) strikes me as odd too
> with its tight coupling and assumption that its operands are
> integral-constants. plus and other arithmetic ops could be 'just an
> operator' with the result type solely dependent on the operands. I
> remember you arguing against this for mpl.. "concept overloading"
> was it? but cant remember why

I don't know what you're talking about. I have no problem with plus
being applied to other kinds of numerical wrapper types.

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

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