[mpl] Accessing the nested value of an invoked placeholder
All, I'm writing some code to filter a vector_c of enum values. I have some existing structs which are templatized on those enum types and I'm having some trouble accessing those structs using placeholders. Following is code which hopefully clarifies: #include <boost/cstdint.hpp> #include <boost/mpl/assert.hpp> #include <boost/mpl/copy_if.hpp> #include <boost/mpl/vector_c.hpp> #include <boost/type_traits.hpp> #include <iostream> using boost::mpl::placeholders::_; enum MyEnum { val1, val2, }; template <MyEnum me> struct trait; template <> struct trait<val1> { typedef boost::uint16_t type; }; template <> struct trait<val2> { typedef boost::uint8_t type; }; //PROBLEM: The 'T' passed in is _, not what it substitutes for. template <typename T> struct traitMeta : trait<T::value> {}; typedef boost::mpl::vector_c<MyEnum, val1, val2> Vec; //For each item in Vec, determine if trait<_>::type matches T. If so, add it. template <typename T> struct TypeIs : boost::mpl::copy_if<Vec, boost::is_same<typename traitMeta<_>::type, T> > {}; BOOST_MPL_ASSERT((TypeIs<boost::uint16_t>::type, boost::mpl::vector_c<MyEnum, val1>)); int main() { return 0; } //END CODE I would assume from reading the book and documentation that mpl::apply or mpl::lambda would be best to use here, but my attempts to do so haven't been successful. I'd appreciate any guidance. Thanks, Nate
At Wed, 27 Oct 2010 12:29:14 -0600, Nathan Crookston wrote:
All,
I'm writing some code to filter a vector_c of enum values. I have some existing structs which are templatized on those enum types and I'm having some trouble accessing those structs using placeholders. Following is code which hopefully clarifies:
Hi Nathan,
#include <boost/cstdint.hpp> #include <boost/mpl/assert.hpp> #include <boost/mpl/copy_if.hpp> #include <boost/mpl/vector_c.hpp> #include <boost/type_traits.hpp> #include <iostream>
using boost::mpl::placeholders::_;
enum MyEnum { val1, val2, };
template <MyEnum me> struct trait;
template <> struct trait<val1> { typedef boost::uint16_t type; };
template <> struct trait<val2> { typedef boost::uint8_t type; };
//PROBLEM: The 'T' passed in is _, not what it substitutes for. template <typename T> struct traitMeta : trait<T::value> {};
typedef boost::mpl::vector_c<MyEnum, val1, val2> Vec;
//For each item in Vec, determine if trait<_>::type matches T. If so, add it. template <typename T> struct TypeIs : boost::mpl::copy_if<Vec, boost::is_same<typename traitMeta<_>::type, T> > {};
This is a problem; reaching inside a template for a member (like ::type) always causes it to be instantiated. That means traitMeta<_>::type gets evaluated early, which isn't what you want. I think if you just drop the ::type you'll get the semantics you want.
//END CODE
I would assume from reading the book and documentation that mpl::apply or mpl::lambda would be best to use here, but my attempts to do so haven't been successful. I'd appreciate any guidance.
mpl::copy_if uses apply (which uses lambda) internally, so you don't have to. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
Hi Dave, On Wed, Oct 27, 2010 at 2:59 PM, David Abrahams <dave@boostpro.com> wrote: <snip code>
This is a problem; reaching inside a template for a member (like ::type) always causes it to be instantiated. That means traitMeta<_>::type gets evaluated early, which isn't what you want. I think if you just drop the ::type you'll get the semantics you want.
Ah, this makes sense. Thanks for the explanation, things are working now. Nate
participants (2)
-
David Abrahams
-
Nathan Crookston