Re: [Boost-users] [mpl] newbie question

Top posting because I'm going to remark about this thread in general, but this message is a fine example. Andy seems to be speaking (mostly) about int_<>, integral_c, etc (I'll just say the incorrect 'int<>') and plus; David is talking about transform. I think, but can't say for sure, that Andy wants plus to work 'as expected' and always return int<>, not just 'concept-identical' to int. Maybe it does, I'm not sure. And/or he wants transform ***when applied to int<> with plus, etc*** to return int<>. David, says, that ***in general*** transform can't make the return type "match" (in Andy's stricter sense) the inputs. Maybe it could for the special case of int<>? IMO, that would be quite hard, as the point of the templates is to be general. Do I have this right, in any sense? P.S. for David, below: Date: Sat, 25 Feb 2006 10:22:57 -0500
From: David Abrahams
Subject: Re: [Boost-users] [mpl] newbie question To: boost-users@lists.boost.org Message-ID: Content-Type: text/plain; charset=us-ascii "Andy Little"
writes: I think we need a little bit more context here.
OP David Abrahams
Andy Little (me)
Just trying to use mpl::transform on a vector of int's and I can't seem to get it working properly. Can anyone see what's wrong?? I'm trying to perform
vector_c
+ vector_c = vector_c The is_same function always returns false when I compile and run it.
The result of the transform is only required to be "concept-identical"
the line above says "the transform"
to the result you're looking for.
IMO that behaviour is sloppy. I see no reason why (at least)
boost::is_same < plus< int_<1> ,int_<1> >::type, int_<2> > shouldnt be true.
Your change from "the transform" to "being about transform" above is problematic for me.
I don't know what you mean. Nobody wrote "the transform" above. as mentioned, he did, but that doesn't mean I understand the point he is trying to make. Don't make this complicated. It is very simple: I made a statemnt
*about the behavior of transform*, and you replied "that behavior is sloppy," and then proceeded to go on about something only distantly related (the type of results of arithmetic operations).
The behavior I was describing is not sloppy. To make the library behave differently would introduce a huge overhead in implementation code that is more likely than not to slow down compilation of user programs.
Let me be a little more explicit:
transform
>::type is likely to be a specialization of vectorN where N is a numeral. Therefore, testing it against a vector_c specialization using is_same will always fail. That is the behavior I was referring to.
I wouldn't care much what you said, except for that you're doing this in a thread where impressionable "newbies" are reading, and I don't want them to misunderstand the library design or the implementation decisions and their costs/benefits. Your statement above not only unfairly maligns Aleksey's work, it is misleading.
-- Dave Abrahams Boost Consulting www.boost-consulting.com

"Gottlob Frege" wrote [...]
Do I have this right, in any sense?
I think things should work as expected. Users failed expectations might be because of a fault in the design...
P.S. for David, below:
[...] ... OTOH at that point I realised this wasnt going to be a very productive thread ;-) regards Andy Little

"Gottlob Frege"
Top posting because I'm going to remark about this thread in general, but this message is a fine example.
Andy seems to be speaking (mostly) about int_<>, integral_c, etc (I'll just say the incorrect 'int<>') and plus; David is talking about transform.
I think, but can't say for sure, that Andy wants plus to work 'as expected' ^^^^^^^^^^^^^^^^^^ and always return int<>, not just 'concept-identical' to int.
Andy, please take note: what you want is still unclear to people other than me. Since "as expected" is vague, and your statement seems a little too sweeping, I'll say it this way: I (Dave) think, but can't say for sure, that Andy wants plus to always return an int_ specialization when all the inputs are specializations of int_. I think, but can't say for sure, that he also wants a different specification for the behavior of plus, and all the other arithmetic operators.
Maybe it does, I'm not sure. And/or he wants transform ***when applied to int<> with plus, etc*** to return int<>.
David, says, that ***in general*** transform can't make the return type "match" (in Andy's stricter sense) the inputs.
Maybe it could for the special case of int<>? IMO, that would be quite hard, as the point of the templates is to be general.
I don't think we can do it. However, it's certainly possible to make
the *elements* of the resulting container be int_ specializations
whenever the operation has the form:
transform

"David Abrahams" wrote
Since "as expected" is vague, and your statement seems a little too sweeping, I'll say it this way:
I (Dave) think, but can't say for sure, that Andy wants plus to always return an int_ specialization when all the inputs are specializations of int_.
The as expected part is important and necessarily vague because the subject of
the thread is basically about why mpl doesnt work as the OP expects. User
expectations are often vague, but this one is consistent from quite a few
people. ( Its mentioned in passing in the mpl book AFAIK).
The expectation ( based on OP's light reading of examples I guess ) is this
assert( boost::is_same <
mpl::transform<
vector_c
::value == true);
Anyway the point is I dont think its impossible to come up with an alternative design as you seem to be suggesting. 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 But in both cases the mpl designers argument is that these are only interfaces ,designed to save a bit of typing. 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. 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. 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. This as well as seeming arbitrary, makes int_'s and long_'s and vector_c basically superfluous IMO. 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'm out of time for now. Apologies that the above isnt as clear as I would like. regards Andy Little

"Andy Little" wrote
The expectation ( based on OP's light reading of examples I guess ) is this
assert( boost::is_same < mpl::transform< vector_c
,vector_c ,some_plus_func > ::type , vector_c ::value == true);
Personally I think ( even ) that is with (some mods) a realistic expectation.
FWIW Enclosed is a small sample which seems to work ok in VC7.1 and gcc4.01,
bearing in mind its based on expectations not status quo
Formatting of output works best in vc7.1 BTW.
IOW Its not impossible to make it work. Might be useful as a relatively simple
demo anyway. Could also be used to explain the reasons for rejecting this
approach too of course ;-)
regards
Andy Little
begin 666 test.cpp
M+RH-"B @('-T86YD86QO;F4@=F5C=&]R7V,@861D('5S:6YG('1R86YS9F]R
M;5]C#0H@("!T97-T960@5D,W+C$@9V-C(#0N,#$-"BHO#0H-"FYA;65S<&%C
M92!M>7L-"@T*(" @("\O

"Andy Little"
"Andy Little" wrote
The expectation ( based on OP's light reading of examples I guess ) is this
assert( boost::is_same < mpl::transform< vector_c
,vector_c ,some_plus_func > ::type , vector_c ::value == true);
Personally I think ( even ) that is with (some mods) a realistic expectation.
FWIW Enclosed is a small sample which seems to work ok in VC7.1 and gcc4.01, bearing in mind its based on expectations not status quo Formatting of output works best in vc7.1 BTW.
IOW Its not impossible to make it work.
<sigh> Nobody ever said it was impossible. What you're doing here fails one of the primary design goals of the MPL: in the same way that the STL iterator abstraction avoids an MxN explosion of algorithm implementations (where M is the number of algorithms and N is the number of data structures), the MPL is designed to avoid the same kind of explosion. If you follow this path, you will end up reimplementing every algorithm once for every data structure. Finally, even if you do meet the expectation, it will be incredibly fragile: it becomes impossible to extend the library (or user code) and continue to meet expectations. You add a new algorithm, and then suddenly the expectation is broken for any user-defined sequence types that you didn't know about. You add a new sequence, and the expectation is broken for any user-defined algorithms you didn't know about.
Might be useful as a relatively simple demo anyway. Could also be used to explain the reasons for rejecting this approach too of course ;-)
I hope you find my explanation above satisfactory. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" wrote
"Andy Little" writes:
"Andy Little" wrote
The expectation ( based on OP's light reading of examples I guess ) is this
assert( boost::is_same < mpl::transform< vector_c
,vector_c ,some_plus_func > ::type , vector_c ::value == true);
Personally I think ( even ) that is with (some mods) a realistic expectation.
FWIW Enclosed is a small sample which seems to work ok in VC7.1 and gcc4.01, bearing in mind its based on expectations not status quo Formatting of output works best in vc7.1 BTW.
IOW Its not impossible to make it work.
<sigh> Nobody ever said it was impossible.
What you're doing here fails one of the primary design goals of the MPL: in the same way that the STL iterator abstraction avoids an MxN explosion of algorithm implementations (where M is the number of algorithms and N is the number of data structures), the MPL is designed to avoid the same kind of explosion. If you follow this path, you will end up reimplementing every algorithm once for every data structure.
Finally, even if you do meet the expectation, it will be incredibly fragile: it becomes impossible to extend the library (or user code) and continue to meet expectations. You add a new algorithm, and then suddenly the expectation is broken for any user-defined sequence types that you didn't know about. You add a new sequence, and the expectation is broken for any user-defined algorithms you didn't know about.
Might be useful as a relatively simple demo anyway. Could also be used to explain the reasons for rejecting this approach too of course ;-)
I hope you find my explanation above satisfactory.
I understand it. I concede that I was wrong to argue about it, so I'm sorry for wasting your and everyone elses time. Of course If anyone can implement the dimensional-analysis part of pqs ( in the Boost vault in The Physical Quantities Units directory) , such that it compiles faster than it does currently, by using mpl, then I will be happy to re-implement it using mpl. Otherwise I dont currently see the benefit. That may change of course if for some reason I need the mpl features you mention above, though currently the dimensional-analysis code seems quite stable. The only reason I can see might be to make the sequence of base-units modifiable in length, however my inclination would be to do this by means of a config macro . Anyway I shall be interested to see what Noel Belcourt comes up with. My feeling is that mpl is unlikely to beat the current set up in terms of compilation speed but I'd be happy to be proved wrong. It is of course a very unfair challenge because my code is customised for this one job , whereas mpl must be generic. regards Andy Little

"Andy Little"
The expectation ( based on OP's light reading of examples I guess ) is this
assert( boost::is_same < mpl::transform< vector_c
,vector_c ,some_plus_func > ::type , vector_c >::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
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>::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
some_plus_func; or
template
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
,vector_c ,some_plus_func<0,0> > ::type , vector_c >::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
>::type, mpl::vector ,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
participants (3)
-
Andy Little
-
David Abrahams
-
Gottlob Frege