Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
Paul Mensonides [EMAIL PROTECTED] writes: - Original Message - From: David Abrahams [EMAIL PROTECTED] snip AFAICT from browsing it quickly, the significance of TTP in your code is that you are passing templates instead of types as functions in the interfaces to your metafunctions, which I think is inadvisable, because it eventually breaks metafunction polymorphism. Not really. That is the purpose of various types of partial binding constructs. The only real way to break metafunction polymorphism is to use non-type template arguments in the the template template parameters, and not even that will totally break it. I mean that if a metafunction is a template instead of a type you can't treat it polymorphically with other things, e.g. you can't put it in a type sequence. Strictly not using template template parameters has its own problems since you can't pass namespaces as arguments, etc.. This can complicate a design real quick as you make more and more indirection layers: struct metafunction { templateclass T struct actual_metafunction { // ... }; }; vs. templateclass T struct metafunction { // ... }; mpl::lambda handles the transformation from the latter to the former. I'm not saying the convention is bad, just that it has its own set of associated problems. Other than that, the final interface you show is one that's acheivable without TTP at all. Yes, you can do it without TTP, but it isn't as clean. (I only had a rough idea in my head when I made the remark.) You pay a price for the abstraction that you mention by metafunction polymorphism. Hmm? The difference is that I prefer to do that abstraction external to the core implementation and provide a bridge layer for common usages. In any case, it turns out to be slightly longer anyway because I forgot about the need for ::template when one (or all) of the parameters a dependent. Yes, the language syntax gets in the way. However, I was going for a general purpose iterative OR when I started it, rather than just a solution to the particular problem. I basically just had a general idea of something like this: containsT::argint::argdouble::argstd::string::value ...but the ::template makes it longer: containsT ::template argint ::template argdouble ::template argstd::string ::value Altogether, I'm quite pleased with the mechanism, as I find the linear typelist implementation neat, and I've never seen anything like that implementation. libs/python/test/if_else.cpp might be of interest to you. The template classes fold_left and fold_right are not even metafunctions in any normal sense. I wouldn't know what to call them! They're interesting to a point, but inflexible. Any given usage is restricted to working on sequences of a particular length. -- David Abrahams [EMAIL PROTECTED] * http://www.boost-consulting.com Boost support, enhancements, training, and commercial distribution ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
- Original Message - From: David Abrahams [EMAIL PROTECTED] ... I mean that if a metafunction is a template instead of a type you can't treat it polymorphically with other things, e.g. you can't put it in a type sequence. Yes, you can with the appropriate binders. That is what I meant. struct metafunction { templateclass T struct actual_metafunction { // ... }; }; vs. templateclass T struct metafunction { // ... }; mpl::lambda handles the transformation from the latter to the former. Yeah, I retract that statement. ;) It is easy to map them back and forth. I'm not saying the convention is bad, just that it has its own set of associated problems. Other than that, the final interface you show is one that's acheivable without TTP at all. Yes, you can do it without TTP, but it isn't as clean. (I only had a rough idea in my head when I made the remark.) You pay a price for the abstraction that you mention by metafunction polymorphism. Hmm? Code clarity. As abstraction goes up, clarity goes down. Altogether, I'm quite pleased with the mechanism, as I find the linear typelist implementation neat, and I've never seen anything like that implementation. libs/python/test/if_else.cpp might be of interest to you. I'll take a look. The template classes fold_left and fold_right are not even metafunctions in any normal sense. I wouldn't know what to call them! They're interesting to a point, but inflexible. Any given usage is restricted to working on sequences of a particular length. Yes, however, the intended purpose is as an inline definition, not as a sequence type, and it doesn't require the code replication necessary to support something like mpl::vector. I'm not saying that it's super great overall. I'm merely saying that it amuses me, and I like it. ;) Paul Mensonides ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
Paul Mensonides [EMAIL PROTECTED] writes: - Original Message - From: David Abrahams [EMAIL PROTECTED] Paul Mensonides [EMAIL PROTECTED] writes: Which could be even shorter yet if we could get away with template template parameters. We can and do. How would you imagine it would be spelled with TTP? You asked for it. ;) Beware, this is the work of a sick mind! Basically, this implementation reduces the sample to an inline fold of the form: operation::stepX::stepY::stepZ::[ value | type ] ...where 'operation' is the type of operation and where '[ value | type ]' is either 'value' or 'type'. Ultimately, we get something similar to this (with the help of a macro to handle the ::template that is sometimes necessary): is_presentT item bool item int item double item std::string ::value snip AFAICT from browsing it quickly, the significance of TTP in your code is that you are passing templates instead of types as functions in the interfaces to your metafunctions, which I think is inadvisable, because it eventually breaks metafunction polymorphism. Other than that, the final interface you show is one that's acheivable without TTP at all. -- David Abrahams [EMAIL PROTECTED] * http://www.boost-consulting.com Boost support, enhancements, training, and commercial distribution ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
- Original Message - From: David Abrahams [EMAIL PROTECTED] snip AFAICT from browsing it quickly, the significance of TTP in your code is that you are passing templates instead of types as functions in the interfaces to your metafunctions, which I think is inadvisable, because it eventually breaks metafunction polymorphism. Not really. That is the purpose of various types of partial binding constructs. The only real way to break metafunction polymorphism is to use non-type template arguments in the the template template parameters, and not even that will totally break it. Strictly not using template template parameters has its own problems since you can't pass namespaces as arguments, etc.. This can complicate a design real quick as you make more and more indirection layers: struct metafunction { templateclass T struct actual_metafunction { // ... }; }; vs. templateclass T struct metafunction { // ... }; I'm not saying the convention is bad, just that it has its own set of associated problems. Other than that, the final interface you show is one that's acheivable without TTP at all. Yes, you can do it without TTP, but it isn't as clean. (I only had a rough idea in my head when I made the remark.) You pay a price for the abstraction that you mention by metafunction polymorphism. The difference is that I prefer to do that abstraction external to the core implementation and provide a bridge layer for common usages. In any case, it turns out to be slightly longer anyway because I forgot about the need for ::template when one (or all) of the parameters a dependent. However, I was going for a general purpose iterative OR when I started it, rather than just a solution to the particular problem. I basically just had a general idea of something like this: containsT::argint::argdouble::argstd::string::value ...but the ::template makes it longer: containsT ::template argint ::template argdouble ::template argstd::string ::value Altogether, I'm quite pleased with the mechanism, as I find the linear typelist implementation neat, and I've never seen anything like that implementation. The template classes fold_left and fold_right are not even metafunctions in any normal sense. I wouldn't know what to call them! Paul Mensonides ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
Paul Mensonides [EMAIL PROTECTED] writes: Which could be even shorter yet if we could get away with template template parameters. We can and do. How would you imagine it would be spelled with TTP? -- David Abrahams [EMAIL PROTECTED] * http://www.boost-consulting.com Boost support, enhancements, training, and commercial distribution ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
- Original Message - From: David B. Held [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Thursday, January 09, 2003 1:16 PM Subject: [boost] Re: Re: How to do this in withboost--assert(typeid(T)==typeid(bool) ) Paul Mensonides [EMAIL PROTECTED] wrote in message 000901c2b823$1e7f4aa0$8c00a8c0@c161550b">news:000901c2b823$1e7f4aa0$8c00a8c0@c161550b... - Original Message - From: Terje Slettebø [EMAIL PROTECTED] [...] BOOST_STATIC_ASSERT((\ boost::is_sameT, bool::value ||\ boost::is_sameT, int::value ||\ boost::is_sameT, double::value ||\ boost::is_sameT, std::string::value )); And this is still bulkier and less elegant than the two-line MPL solution. ;) Which could be even shorter yet if we could get away with template template parameters. Paul Mensonides ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
From: David B. Held [EMAIL PROTECTED] Paul Mensonides [EMAIL PROTECTED] wrote in message 000901c2b823$1e7f4aa0$8c00a8c0@c161550b">news:000901c2b823$1e7f4aa0$8c00a8c0@c161550b... From: Terje Slettebø [EMAIL PROTECTED] [...] BOOST_STATIC_ASSERT((\ boost::is_sameT, bool::value ||\ boost::is_sameT, int::value ||\ boost::is_sameT, double::value ||\ boost::is_sameT, std::string::value )); And this is still bulkier and less elegant than the two-line MPL solution. ;) I agree. I had actually missed Dave Abrahams (lastname used, as there's a lot of Dave's here. :) ) solution, but I found it, now. I think was an elegant way of doing it. And, yeah, I didn't think of that you don't need backslashes when _calling_ a macro, only when defining it. Regards, Terje ___ Unsubscribe other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Re: [boost] Re: Re: How to do this inwithboost--assert(typeid(T)==typeid(bool) )
- Original Message - From: David Abrahams [EMAIL PROTECTED] Paul Mensonides [EMAIL PROTECTED] writes: Which could be even shorter yet if we could get away with template template parameters. We can and do. How would you imagine it would be spelled with TTP? You asked for it. ;) Beware, this is the work of a sick mind! Basically, this implementation reduces the sample to an inline fold of the form: operation::stepX::stepY::stepZ::[ value | type ] ...where 'operation' is the type of operation and where '[ value | type ]' is either 'value' or 'type'. Ultimately, we get something similar to this (with the help of a macro to handle the ::template that is sometimes necessary): is_presentT item bool item int item double item std::string ::value Also, the same underlying implementation is used to build a completely linearized typelist mechanism: typedef gen_typelist item char item signed char item unsigned char item short item unsigned short item int item unsigned item long item unsigned long ::type integral_types; Here is the implementation (from scratch): // identity: yields its template argument as a typedef templateclass T struct identity { typedef T type; }; // map_integral: everyone's favorite plus a typedef //representing the type of its stored value //(this is just a hack because I was too lazy to detect it, //and you can't do it with partial specialization because //of the dependent second parameter.) templateclass T, T V struct map_integral : identityT { static const T value = V; }; templateclass T, T V const T map_integralT, V::value; // has_member_value: metafunction that returns // true if its template argument has a nested value // named 'value' templateclass T struct has_member_value { private: templatelong struct helper; templateclass U static char check(helperU::value*); templateclass U static char ( check(...))[2]; public: static const bool value = sizeof(checkT(0)) == 1; }; templateclass T const bool has_member_valueT::value; namespace detail { // fold_nil: placeholder for no previous state // it is used by fold_right struct fold_nil; // fold_helper: the opposite of fold_nil // it stores state needed for fold_right to reverse // its the element order and use fold_left templateclass parent, class element struct fold_helper { }; // fold_reversal: metafunction that participates in // building a reversed list of elements. templateclass build, class struct fold_reversal; // specialization for no previous state templateclass build struct fold_reversalbuild, fold_nil { typedef build type; }; // specialization otherwise templateclass build, class parent, class element struct fold_reversalbuild, fold_helperparent, element { typedef typename fold_reversal typename build::template stepelement, parent ::type type; }; // value_if: yields a nested static constant if 'T' has // a 'value' member. If so, 'T' must also have a member 'type' // that denotes the 'type' of the static constant. // This can be deduced, but I didn't feel like bothering to // do it here. (This is the reason that map_integral above has // a 'type' typedef.) templateclass T, bool = has_member_valueT::value struct value_if { }; templateclass T struct value_ifT, true : map_integraltypename T::type, T::value { }; } // detail // the fold_left and fold_right meta-something-or-others // perform an unraveled fold in a strange way: //'fold_leftop, state, transform::stepX::stepY::stepZ::type' // //effectively yields: //op(transform(Z), op(transform(Y), op(transform(X), state))) // // vice versa with fold_right. // // These 'metafunctions' contain a nested template 'step' // which represents a fold step. These nested templates // inject there own name via inheritance of their parent // classes. This allows the syntax: fold_left...::stepint::stepdouble // etc.. I'm not sure if this is actually legal, but it works on Comeau C++. // If it isn't legal, I'd need some kind of jumper typedef that identifies the // base class, which would alter the final syntax to: // fold_left...::stepint::base::stepdouble etc. // ...which is trivial handled by local sugar macros anyway. // // the 'op' parameter is the fold operation, which is instantiated // with the current element and the current state. // // the 'state' parameter is the initial state of the accumulation // // the 'transform' parameter is a simple way to modify each element // however you like. The 'is_present' implementation uses this parameter // with a partially bound 'is_same' metafunction, and uses a logical-or // metafunction as the 'op' parameter. The 'identity' metafunction is // the default and simply does nothing. // fold_left template templateclass _element, class _state class op, class state, templateclass class transform = identity struct fold_left {