Tuples: Can someone help me generalize this?
Hello, boost-users, what I am trying to accomplish is a generic collection of N objects of type Type. I need for the N objects to be tightly packed and I would like the collection to be constructible in this way: uniform_vector<3, float> my_point(1.0f, 2.1f, 3.2f); I'm very new to the template (meta)programming scene and I would like to get better at it, so any advice you could give that would be instructive in that regard would be much appreciated. The code below is what I have come up with. Question 1: Am I reinventing the wheel at all? In other words is there something I can just typedef to get this functionality? Question 2: If not, how could I generalize this? Is there a template metaprogramming way? I'm sure it can be done with the preprocessor but I'm no good with macros... but then again I'm not much good with templates either at least not by a boost mailing list standard anyway. :) Thanks, Derrick. // -- uniform_vector.hpp ------------------------------------------------------------------------ #ifndef DJH_UNIFORM_VECTOR_HPP #define DJH_UNIFORM_VECTOR_HPP #include <boost/tuple/tuple.hpp> namespace djh { template <unsigned int N, class Type> struct uniform_vector; template <class Type> struct uniform_vector<0, Type>; template <class Type> struct uniform_vector<1, Type> { static const unsigned int size = 1; typedef boost::tuple<Type> type; }; template <class Type> struct uniform_vector<2, Type> { static const unsigned int size = 2; typedef boost::tuple<Type, Type> type; }; template <class Type> struct uniform_vector<3, Type> { static const unsigned int size = 3; typedef boost::tuple<Type, Type, Type> type; }; template <class Type> struct uniform_vector<4, Type> { static const unsigned int size = 4; typedef boost::tuple<Type, Type, Type, Type> type; }; } #endif
AMDG Derrick Hathaway wrote:
Hello, boost-users, what I am trying to accomplish is a generic collection of N objects of type Type. I need for the N objects to be tightly packed and I would like the collection to be constructible in this way:
uniform_vector<3, float> my_point(1.0f, 2.1f, 3.2f);
I'm very new to the template (meta)programming scene and I would like to get better at it, so any advice you could give that would be instructive in that regard would be much appreciated. The code below is what I have come up with.
Question 1: Am I reinventing the wheel at all? In other words is there something I can just typedef to get this functionality?
Question 2: If not, how could I generalize this? Is there a template metaprogramming way? I'm sure it can be done with the preprocessor but I'm no good with macros... but then again I'm not much good with templates either at least not by a boost mailing list standard anyway. :)
Here's some template code that creates an appropriate tuple type. #include <boost/mpl/transform.hpp> #include <boost/mpl/always.hpp> #include <boost/mpl/range_c.hpp> #include <boost/mpl/back_inserter.hpp> #include <boost/fusion/include/vector.hpp> #include <boost/fusion/include/mpl.hpp> #include <iostream> // create a sequence of 5 elements typedef boost::mpl::range_c<int, 0, 5> range; // convert all the elements to float and make the result a fusion vector. typedef boost::mpl::transform<range, boost::mpl::always<float>, boost::mpl::back_inserter<boost::fusion::vector<> > >::type tuple_type; int main() { tuple_type t(0, 1, 2, 3, 4); std::cout << typeid(tuple_type).name() << std::endl; } In Christ, Steven Watanabe
AMDG
Derrick Hathaway wrote:
Hello, boost-users, what I am trying to accomplish is a generic collection of N objects of type Type. I need for the N objects to be tightly packed and I would like the collection to be constructible in this way:
uniform_vector<3, float> my_point(1.0f, 2.1f, 3.2f);
I'm very new to the template (meta)programming scene and I would like to get better at it, so any advice you could give that would be instructive in that regard would be much appreciated. The code below is what I have come up with.
Question 1: Am I reinventing the wheel at all? In other words is there something I can just typedef to get this functionality?
Question 2: If not, how could I generalize this? Is there a template metaprogramming way? I'm sure it can be done with the preprocessor but I'm no good with macros... but then again I'm not much good with templates either at least not by a boost mailing list standard anyway. :)
Here's some template code that creates an appropriate tuple type.
#include <boost/mpl/transform.hpp> #include <boost/mpl/always.hpp> #include <boost/mpl/range_c.hpp> #include <boost/mpl/back_inserter.hpp> #include <boost/fusion/include/vector.hpp> #include <boost/fusion/include/mpl.hpp>
#include <iostream>
// create a sequence of 5 elements typedef boost::mpl::range_c<int, 0, 5> range; // convert all the elements to float and make the result a fusion vector. typedef boost::mpl::transform<range, boost::mpl::always<float>, boost::mpl::back_inserter<boost::fusion::vector<> > >::type tuple_type;
int main() { tuple_type t(0, 1, 2, 3, 4); std::cout << typeid(tuple_type).name() << std::endl; }
In Christ, Steven Watanabe
Thank you, Sir, for your quick response. I just got around to testing it, and I've run into a snag. a fusion::vector is larger than the sum of it's parts, and I would like something that is not. In other words: sizeof(vector<float, float>) != sizeof(float) + sizeof(float) A tuple seems to fit, as I described earlier, but I'm not sure how to generalize this. I've thought that there might be a way to generalize a tuple to provide an interface like my_tuple<N, Type> using the cons. Any thoughts? Thanks again. Derrick
AMDG Derrick Hathaway wrote:
Thank you, Sir, for your quick response. I just got around to testing it, and I've run into a snag. a fusion::vector is larger than the sum of it's parts, and I would like something that is not. In other words:
sizeof(vector<float, float>) != sizeof(float) + sizeof(float)
Please create a trac ticket for this. It looks like EBCO is not working properly, because the compiler refuses to allocate two instances of boost::fusion::sequence_root at the same address.
A tuple seems to fit, as I described earlier, but I'm not sure how to generalize this. I've thought that there might be a way to generalize a tuple to provide an interface like my_tuple<N, Type> using the cons. Any thoughts?
Unfortunately cons doesn't quite work because it it doesn't have the constructor you want. You can use the general mpl::inserter to create a specialization of tuple. #include <boost/mpl/transform.hpp> #include <boost/mpl/always.hpp> #include <boost/mpl/range_c.hpp> #include <boost/mpl/inserter.hpp> #include <boost/tuple/tuple.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <iostream> template<class Tuple, class T> struct tuple_push_front; template<BOOST_PP_ENUM_PARAMS(9, class T), class T> struct tuple_push_front<boost::tuple<BOOST_PP_ENUM_PARAMS(9, T)>, T> { typedef boost::tuple<T, BOOST_PP_ENUM_PARAMS(9, T)> type; }; // create a sequence of 5 elements typedef boost::mpl::range_c<int, 0, 5> range; // convert all the elements to float and make the result a fusion vector. typedef boost::mpl::transform<range, boost::mpl::always<float>, boost::mpl::inserter< boost::tuple<>, tuple_push_front<boost::mpl::_1, boost::mpl::_2> >
::type tuple_type;
int main() { tuple_type t(0, 1, 2, 3, 4); std::cout << typeid(tuple_type).name() << std::endl; } In Christ, Steven Watanabe
participants (2)
-
Derrick Hathaway
-
Steven Watanabe