Understanding MPL and using '::type'
I am making another effort to understand MPL. I have the book by David Abrahams and Aleksey Gurtovoy, "C++ Template Programming", which is my basic source for learning the library, and I have the Boost documentation for the MPL. After reading chapter 3 again I think I understand the basic concepts more easily. However I am still missing something basic, which I think can be given the name: "How do I understand when to append and when not to append the '::type' to a metaprogramming construct built with MPL". Let me first say that I fully understand that '::type' is the way that the MPL returns compile time data in its metafunctions. Also that I understand that '::type' may refer to compile time numeric data ( including bool ) in the eventual form of '::type::value' and that '::value' is often supplied as a shorthand for compile time numeric data. Finally I do understand that to pass metafunctions around when a type is needed the MPL uses a metafunction class, which is a type and not a template. What I am missing is how to determine when using MPL functionality, whether it be data types, sequences, iterators, algorithms, or views being manipulated, when to append '::type' to the end of the intermediary expression or not. Let me give some examples of my confusion based on my reading in the MPL book listed above. I am reading about algorithms and I see an example whose logic I perfectly understand, and whose syntax goes like this: template<class Seq> struct biggest_float_as_double : mpl::deref < typename mpl::max_element < typename mpl::replace < Seq, float, double >::type, mpl::less < mpl::sizeof_<_1>, mpl::sizeof_<_2> > >::type
{};
In two cases in the nested construct above one uses the 'typename
xxx<...>::type' construct whereas in one case one does not. There seems
to be some logic or rule about this but I do not understand what it is.
A few pages later in the text I see:
typedef mpl::vector
<
mpl::vector_c
S; typedef mpl::transform < S, mpl::front<_>, mpl::inserter < mpl::int_<0>, mpl::plus<_,_>
::type sum; Here we have another nested mpl construct and I do understand the logic of it, but here there are no internal nested '::type' statements. Once again I am utterly puzzled about the whys and wherefores of using or not using '::type'. Finally I turn the page and I see this MPL construct: template<class Seq> struct reverse : mpl::fold < Seq, typename mpl::clear<Seq>::type, mpl::push_front<_,_>
{}; Once again I can follow the logic and the explanation of mpl::fold, but I have no idea by what rule one of the nested constructs has '::type' appended and the next one does not. As a naive learner of the MPL I would have thought it would have been much easier to use if every MPL construct ( mpl::xxx... ) returned a '::type', and then this business of when to use and when not to use '::type' would have been regularized, but evidently MPL does not work that way. Since I still do not understand the rule about this, hopefully someone who knows MPL, and who realizes that while I understand the basic concepts I am still trying to understand it, can enlighten me on this subject.
AMDG Greetings from BoostCon, Edward Diener wrote:
template<class Seq> struct biggest_float_as_double : mpl::deref < typename mpl::max_element < typename mpl::replace < Seq, float, double >::type, mpl::less < mpl::sizeof_<_1>, mpl::sizeof_<_2> > >::type
{};
In two cases in the nested construct above one uses the 'typename xxx<...>::type' construct whereas in one case one does not. There seems to be some logic or rule about this but I do not understand what it is.
The ::type is no needed on the deref because we want biggest_float_as_double to inherit type nested ::type of deref. Thus, biggest_float_as_double<S>::type will be deref<...>::type. This technique is known as metafunction forwarding.
A few pages later in the text I see:
typedef mpl::vector < mpl::vector_c
, mpl::vector_c , mpl::vector_c S;
typedef mpl::transform < S, mpl::front<_>, mpl::inserter < mpl::int_<0>, mpl::plus<_,_>
::type sum;
Here we have another nested mpl construct and I do understand the logic of it, but here there are no internal nested '::type' statements. Once again I am utterly puzzled about the whys and wherefores of using or not using '::type'.
front<_> is an MPL lambda expression. It is not supposed to be evaluated immediately. mpl::transform will evaluate it substituting each element of the sequence for _. leaving the ::type of plus<...> is a shortcut which works for numeric metafunctions. There would be no problem with adding a ::type. mpl::inserter is an mpl object rather than an mpl metafunction.
Finally I turn the page and I see this MPL construct:
template<class Seq> struct reverse : mpl::fold < Seq, typename mpl::clear<Seq>::type, mpl::push_front<_,_>
{};
Once again I can follow the logic and the explanation of mpl::fold, but I have no idea by what rule one of the nested constructs has '::type' appended and the next one does not.
Again, mpl::push_front<_,_> is a lambda expression. Its evaluation is delayed. In Christ, Steven Watanabe
Steven Watanabe wrote:
AMDG
Greetings from BoostCon,
Edward Diener wrote:
template<class Seq> struct biggest_float_as_double : mpl::deref < typename mpl::max_element < typename mpl::replace < Seq, float, double >::type, mpl::less < mpl::sizeof_<_1>, mpl::sizeof_<_2> > >::type
{};
In two cases in the nested construct above one uses the 'typename xxx<...>::type' construct whereas in one case one does not. There seems to be some logic or rule about this but I do not understand what it is.
The ::type is no needed on the deref because we want biggest_float_as_double to inherit type nested ::type of deref. Thus, biggest_float_as_double<S>::type will be deref<...>::type. This technique is known as metafunction forwarding.
I understand the case of metafunction forwarding so I do understand why the '::type' is not needed for mpl::deref. That is one of the few rules I do understand which tells me that '::type' is not needed. What I do not understand form the above is why '::type' is needed for mpl::replace and mpl::max_element but it is not needed for mpl::less and mpl::sizeof_. What is the difference in these constructs which require '::type' for some and does not require '::type' for others ?
A few pages later in the text I see:
typedef mpl::vector < mpl::vector_c
, mpl::vector_c , mpl::vector_c S;
typedef mpl::transform < S, mpl::front<_>, mpl::inserter < mpl::int_<0>, mpl::plus<_,_>
::type sum;
Here we have another nested mpl construct and I do understand the logic of it, but here there are no internal nested '::type' statements. Once again I am utterly puzzled about the whys and wherefores of using or not using '::type'.
front<_> is an MPL lambda expression.
According to the book, metafunction classes and placeholder expressions are MPL lambda expressions. Since front<_> is a placeholder expression I understand that it is an MPL lambda expression. By the same definition plus<_,_> is also an MPL lambda expression.
It is not supposed to be evaluated immediately.
OK, I understand that placeholder expressions are not evaluated immediately. What does evaluating an expression immediately have to do with appending '::type' ?
mpl::transform will evaluate it substituting each element of the sequence for _.
Yes, understood.
leaving the ::type of plus<...> is a shortcut which works for numeric metafunctions.
So is the rule in this regard that numeric metafunctions can be passed around without having to specify '::type' ? If so, what set of MPL metafunctions constitute the numeric matfunctions ?
There would be no problem with adding a ::type.
mpl::inserter is an mpl object rather than an mpl metafunction.
So the rule here is that an mpl 'object' never needs a '::type' since it is already a type ? If so, how do I tell which mpl constructs are mpl 'objects' ?
Finally I turn the page and I see this MPL construct:
template<class Seq> struct reverse : mpl::fold < Seq, typename mpl::clear<Seq>::type, mpl::push_front<_,_>
{};
Once again I can follow the logic and the explanation of mpl::fold, but I have no idea by what rule one of the nested constructs has '::type' appended and the next one does not.
Again,
mpl::push_front<_,_>
is a lambda expression. Its evaluation is delayed.
See my question above about evaluating expressions. Eddie
AMDG Edward Diener wrote:
OK, I understand that placeholder expressions are not evaluated immediately.
What does evaluating an expression immediately have to do with appending '::type' ?
When MPL lambda tries to evaluate the placeholder expression it rips the type apart using template specialization and replaces all instances of the placeholders with the correct arguments. By not using ::type it is possible for mpl::lambda to to work without requiring every metafunction to know about lambda.
leaving the ::type of plus<...> is a shortcut which works for numeric metafunctions.
So is the rule in this regard that numeric metafunctions can be passed around without having to specify '::type' ? If so, what set of MPL metafunctions constitute the numeric matfunctions ?
Basically this shortcut works for any MPL metafunction that always returns an MPL Integral constant.
mpl::inserter is an mpl object rather than an mpl metafunction.
So the rule here is that an mpl 'object' never needs a '::type' since it is already a type ? If so, how do I tell which mpl constructs are mpl 'objects' ?
The only answer I can think of is if something would correspond to a function at runtime than you need the ::type. If it refers to something that would be an object like integral constants and vectors, you don't. If your not sure, the only thing to do is look it up. In Christ, Steven Watanabe
Dear All,
I tried to integrate my flex scanner into boost::sprit.
I wrote my own iterator -- the value is int to represent the tokenid:
struct CScannerIterator:std::iterator
Steven Watanabe wrote:
AMDG
Edward Diener wrote:
OK, I understand that placeholder expressions are not evaluated immediately.
What does evaluating an expression immediately have to do with appending '::type' ?
When MPL lambda tries to evaluate the placeholder expression it rips the type apart using template specialization and replaces all instances of the placeholders with the correct arguments. By not using ::type it is possible for mpl::lambda to to work without requiring every metafunction to know about lambda.
I understand the explanation about how placeholders work. The rule you are specifying appears to be that one never adds the '::type' to the end of a placeholder expression when it is being passed to an mpl construct. Is that correct ?
leaving the ::type of plus<...> is a shortcut which works for numeric metafunctions.
So is the rule in this regard that numeric metafunctions can be passed around without having to specify '::type' ? If so, what set of MPL metafunctions constitute the numeric matfunctions ?
Basically this shortcut works for any MPL metafunction that always returns an MPL Integral constant.
OK, I do understand that rule. I can easily isolate the MPL integral constants. Thanks !
mpl::inserter is an mpl object rather than an mpl metafunction.
So the rule here is that an mpl 'object' never needs a '::type' since it is already a type ? If so, how do I tell which mpl constructs are mpl 'objects' ?
The only answer I can think of is if something would correspond to a function at runtime than you need the ::type. If it refers to something that would be an object like integral constants and vectors, you don't.
I wish I knew what the is an mpl function as opposed to what is not an mpl function. Perhaps the mpl algorithms are the mpl functions and everything which is not an algorithm is not an mpl function.
If your not sure, the only thing to do is look it up.
Look up what ? Where in the reference documentation does it tell me whether I need to add '::type' to the end of an mpl construct ?
AMDG Edward Diener wrote:
I understand the explanation about how placeholders work. The rule you are specifying appears to be that one never adds the '::type' to the end of a placeholder expression when it is being passed to an mpl construct. Is that correct ?
You should never add ::type to a placeholder expression at all. Otherwise, the metafunction will probably get very confused.
I wish I knew what the is an mpl function as opposed to what is not an mpl function. Perhaps the mpl algorithms are the mpl functions and everything which is not an algorithm is not an mpl function.
Inserters, Sequences, and the types listed under "Data Types" are not metafunctions. Everything listed in a section with Metafunctions of Algorithms in its name are metafunctions.
If your not sure, the only thing to do is look it up.
Look up what ? Where in the reference documentation does it tell me whether I need to add '::type' to the end of an mpl construct ?
Here are two examples from the reference: template< typename Sequence , typename State , typename ForwardOp > struct accumulate <./accumulate.html> { typedef /unspecified/ type; }; template< typename Seq > struct back_inserter <./back-inserter.html> { // /unspecified/ // /.../ }; In Christ, Steven Watanabe
Edward,
Just wanted to add my 2 cent. That might help. You need ::type when you do
type calculations.
For example:
Access the type stored in a type sequence -> ::type
transform type sequence to another type sequence -> ::type
So meta-algorithms operate on types and result in new types -> ::type
You don't need ::type when you pass parameters or transport the contained
type(s), e.g.
Placeholder transports type parameter to a metafunction -> no ::type
vector of type passed to a metafunction also transports type(s) -> no ::type
Hope that helps.
Ovanes
P.S. sorry that I did not remove unrelated posting lines.
On Tue, May 6, 2008 at 9:44 PM, Steven Watanabe
AMDG
Edward Diener wrote:
I understand the explanation about how placeholders work. The rule you are specifying appears to be that one never adds the '::type' to the end of a placeholder expression when it is being passed to an mpl construct. Is that correct ?
You should never add ::type to a placeholder expression at all. Otherwise, the metafunction will probably get very confused.
I wish I knew what the is an mpl function as opposed to what is not an mpl function. Perhaps the mpl algorithms are the mpl functions and everything which is not an algorithm is not an mpl function.
Inserters, Sequences, and the types listed under "Data Types" are not metafunctions. Everything listed in a section with Metafunctions of Algorithms in its name are metafunctions.
If your not sure, the only thing to do is look it up.
Look up what ? Where in the reference documentation does it tell me whether I need to add '::type' to the end of an mpl construct ?
Here are two examples from the reference:
template< typename Sequence , typename State , typename ForwardOp > struct accumulate <./accumulate.html> { typedef /unspecified/ type; };
template< typename Seq > struct back_inserter <./back-inserter.html> { // /unspecified/ // /.../ };
In Christ, Steven Watanabe
Ovanes Markarian wrote:
Edward,
Just wanted to add my 2 cent. That might help. You need ::type when you do type calculations. For example:
Access the type stored in a type sequence -> ::type
OK
transform type sequence to another type sequence -> ::type
OK
So meta-algorithms operate on types and result in new types -> ::type
There is nothing in the book or documentation reference about "meta-algorithms", whatever they are.
You don't need ::type when you pass parameters or transport the contained type(s), e.g.
What do you mean by the above ?
Placeholder transports type parameter to a metafunction -> no ::type
OK.
vector of type passed to a metafunction also transports type(s) -> no ::type
OK
Hope that helps.
It helps a little but it does not break the two general cases in my mind into all the specific instances of using mpl constructs in the reference. I am gathering that the correct specific way to determine whether or not to append "::type" is to look at the mpl construct and if it is a metafunction, which has its own nested type, always append "::type". More general rules regarding categories of decision about appending "::type", as you have suggested above, seem very vague to me except in specific cases which Steve and you have mentioned. Eddie
Ovanes
P.S. sorry that I did not remove unrelated posting lines.
On Tue, May 6, 2008 at 9:44 PM, Steven Watanabe
mailto:watanabesj@gmail.com> wrote: AMDG
Edward Diener wrote: > I understand the explanation about how placeholders work. The rule you > are specifying appears to be that one never adds the '::type' to the end > of a placeholder expression when it is being passed to an mpl construct. > Is that correct ? >
You should never add ::type to a placeholder expression at all. Otherwise, the metafunction will probably get very confused.
> I wish I knew what the is an mpl function as opposed to what is not an > mpl function. Perhaps the mpl algorithms are the mpl functions and > everything which is not an algorithm is not an mpl function. >
Inserters, Sequences, and the types listed under "Data Types" are not metafunctions. Everything listed in a section with Metafunctions of Algorithms in its name are metafunctions.
>> If your not >> sure, the >> only thing to do is look it up. >> > > Look up what ? Where in the reference documentation does it tell me > whether I need to add '::type' to the end of an mpl construct ? >
Here are two examples from the reference:
template< typename Sequence , typename State , typename ForwardOp > struct accumulate <./accumulate.html> { typedef /unspecified/ type; };
template< typename Seq > struct back_inserter <./back-inserter.html> { // /unspecified/ // /.../ };
In Christ, Steven Watanabe
------------------------------------------------------------------------
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Edward,
please see below.
On Wed, May 7, 2008 at 5:30 AM, Edward Diener
Ovanes Markarian wrote:
Edward,
Just wanted to add my 2 cent. That might help. You need ::type when you do type calculations. For example:
Access the type stored in a type sequence -> ::type
OK
transform type sequence to another type sequence -> ::type
OK
So meta-algorithms operate on types and result in new types -> ::type
There is nothing in the book or documentation reference about "meta-algorithms", whatever they are.
The authors of the book make an analogy between STL and MPL. Especially by introducing meta-functions which are algorithms. Take a look at chapter 6. 6.1. Algorithms, Idioms, Reuse, and Abstraction 6.2. Algorithms in MPL ... MPL meta-functions like transform, sort, copy, remove, reverse, replace etc. are analogies to STL algorithms.
You don't need ::type when you pass parameters or transport the contained type(s), e.g.
What do you mean by the above ?
Placeholder transports type parameter to a metafunction -> no ::type
OK.
vector of type passed to a metafunction also transports type(s) -> no ::type
OK
Hope that helps.
[...] Regards, Ovanes
Ovanes Markarian wrote:
Edward,
please see below.
On Wed, May 7, 2008 at 5:30 AM, Edward Diener
mailto:eldiener@tropicsoft.com> wrote: Ovanes Markarian wrote: > Edward, > > Just wanted to add my 2 cent. That might help. You need ::type when you > do type calculations. > For example: > > Access the type stored in a type sequence -> ::type
OK
> transform type sequence to another type sequence -> ::type
OK
> So meta-algorithms operate on types and result in new types -> ::type
There is nothing in the book or documentation reference about "meta-algorithms", whatever they are.
The authors of the book make an analogy between STL and MPL. Especially by introducing meta-functions which are algorithms. Take a look at chapter 6. 6.1. Algorithms, Idioms, Reuse, and Abstraction 6.2. Algorithms in MPL ...
MPL meta-functions like transform, sort, copy, remove, reverse, replace etc. are analogies to STL algorithms.
I understand what the algorithms of MPL are. You are saying that one always appends "::type" to the result of calling one of the MPL algorithms. That is one rule, which Steve also had already mentioned in a previous reply. So now I have some rules garnered from your and Steve's replies about when to append ::type when using MPL constructs. Thanks for your help. I still find the irregularity of when to use '::type' and when not to use '::type' the most difficult part of using MPL but at least I am further along than before.
Hi,
I am trying to get boost::mpi working on windows system so I have download 1_35_0 version and compile it for msvc 7.1.
When I tried to compile sample code
#include
Steven Watanabe wrote:
AMDG
Edward Diener wrote:
I understand the explanation about how placeholders work. The rule you are specifying appears to be that one never adds the '::type' to the end of a placeholder expression when it is being passed to an mpl construct. Is that correct ?
You should never add ::type to a placeholder expression at all. Otherwise, the metafunction will probably get very confused.
Ok, understood.
I wish I knew what the is an mpl function as opposed to what is not an mpl function. Perhaps the mpl algorithms are the mpl functions and everything which is not an algorithm is not an mpl function.
Inserters, Sequences, and the types listed under "Data Types" are not metafunctions. Everything listed in a section with Metafunctions of Algorithms in its name are metafunctions.
Your firsat sentence above I understand. The ssecond sentence above eludes me.
If your not sure, the only thing to do is look it up.
Look up what ? Where in the reference documentation does it tell me whether I need to add '::type' to the end of an mpl construct ?
Here are two examples from the reference:
template< typename Sequence , typename State , typename ForwardOp > struct accumulate <./accumulate.html> { typedef /unspecified/ type; };
template< typename Seq > struct back_inserter <./back-inserter.html> { // /unspecified/ // /.../ };
OK, I think I get it. If it is described as a metafunction, with its nested type, then '::type' is always used.
participants (5)
-
Adrovic, Ervin
-
Edward Diener
-
Ovanes Markarian
-
peter_foelsche@agilent.com
-
Steven Watanabe