BOOST_FUSION_ADAPT_TPL_STRUCT and template array size

I am trying to iterate over the structure of C ++ templates thanks to BOOST_FUSION_ADAPT_TPL_STRUCT . My structure contains multidimensional arrays of a fixed size, the sizes of which are the parameters of the template. If we look at the Boost example modified for my problem:

#include <iostream> #include <string> #include <boost/fusion/adapted/struct/adapt_struct.hpp> #include <boost/fusion/include/adapt_struct.hpp> // Example: // http://www.boost.org/doc/libs/1_53_0/libs/fusion/doc/html/fusion/adapted/adapt_tpl_struct.html namespace demo { template<typename T, unsigned int SIZE1, unsigned int SIZE2, typename Name, typename Age> struct employee { Name name; Age age; T ar[SIZE1][SIZE2]; }; } // Any instantiated demo::employee is now a Fusion sequence BOOST_FUSION_ADAPT_TPL_STRUCT( (T)(SIZE1)(SIZE2)(Name)(Age), (demo::employee) (T)(SIZE1)(SIZE2)(Name)(Age), (Name, name) (Age, age) (T, ar[SIZE1][SIZE2])) int main() { demo::employee<float, 2, 2, std::string, int> e; e.name = "Bob"; e.age = 25; e.ar[0][0] = e.ar[1][0] = 0.1; e.ar[0][1] = e.ar[1][1] = 0.2; } 

Fail compilation. Moreover, it also fails if we add only an integer template parameter, without even using it for the size of the array.

Is this possible with BOOST_FUSION_ADAPT_TPL_STRUCT ? If not, how do I do this?

+4
source share
2 answers

From doc :

The sequence (template_param0) (template_param1) ... declares the names of the parameters of the template type .

So far, you have the asymmetric SIZE pattern parameter:

 template<typename T, unsigned int SIZE, typename Name, typename Age> struct employee 

You can convert it to a template parameter type and use boost::mpl::int_ as a wrapper for the carry size.

Now your code is compiled .

 template<int Size> struct Array { template<typename T> struct Of { typedef T type[Size]; }; }; namespace demo { template<typename T, typename SIZE, typename Name, typename Age> struct employee { Name name; Age age; T ar[SIZE::value]; }; } // Any instantiated demo::employee is now a Fusion sequence BOOST_FUSION_ADAPT_TPL_STRUCT( (T)(SIZE)(Name)(Age), (demo::employee) (T)(SIZE)(Name)(Age), (Name, name) (Age, age) (typename Array<SIZE::value>::template Of<T>::type, ar)) //... demo::employee<float, int_<2>, std::string, int> e; 
+3
source

After a long conversation with Evgeny Panasyuk, I ended up something completely different. Since I wanted to be able to perform some simple arithmetic operations on data structures, I decided to use Eigen::Map rather than Boost::multi_array , as it offers a wide range of operators, as well as clear documentation.

Thus, the higher-level loop is processed by boost::fusion::for_each , and the lower-level loops are processed by Eigen. Arrays are linearly mapped to eigenvectors. Dimensions are passed in the data_eigen constructor.

 #include <iostream> #include <boost/fusion/adapted/struct/adapt_struct.hpp> #include <boost/fusion/include/adapt_struct.hpp> #include <boost/fusion/algorithm/iteration/for_each.hpp> #include <boost/fusion/include/for_each.hpp> #include <boost/bind.hpp> #include <Eigen/Core> namespace demo { template<typename T, int SIZE1, int SIZE2> struct data { T ar1[SIZE1][SIZE2]; T ar2[SIZE1][SIZE2]; }; template<typename T> struct EigenMap { typedef Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> > type; }; template<typename T> struct data_eigen { template <int SIZE1, int SIZE2> data_eigen(data<T,SIZE1,SIZE2>& src) : ar1(typename EigenMap<T>::type(&src.ar1[0][0], SIZE1*SIZE2)), ar2(typename EigenMap<T>::type(&src.ar2[0][0], SIZE1*SIZE2)) { } typename EigenMap<T>::type ar1; typename EigenMap<T>::type ar2; }; struct print { template<typename T> void operator()(const Eigen::Map<Eigen::Matrix<T, Eigen::Dynamic, 1> >& t) const { std::cout << t.transpose() << std::endl; } }; struct scalarMult { template<typename T, typename U> void operator()(T& t, U& u) const { t *= u; } }; } BOOST_FUSION_ADAPT_TPL_STRUCT ( (T), (demo::data_eigen) (T), (typename demo::EigenMap<T>::type, ar1) (typename demo::EigenMap<T>::type, ar2) ) int main() { typedef float REALTYPE; const int SIZE1 = 2; const int SIZE2 = 2; // Basic data structure with multidimensional arrays demo::data<REALTYPE, SIZE1, SIZE2> d; for (unsigned int i = 0; i < SIZE1; ++i) for (unsigned int j = 0; j < SIZE2; ++j) { d.ar1[i][j] = (i+1)*(j+1); d.ar2[i][j] = i + j; } // Eigen::Map + BOOST_FUSION_ADAPT_TPL_STRUCT demo::data_eigen<REALTYPE> eig_d(d); std::cout << "d:" << std::endl; boost::fusion::for_each(eig_d, demo::print()); std::cout << std::endl; boost::fusion::for_each(eig_d, boost::bind<void>(demo::scalarMult(), _1, 2.0)); std::cout << "2 * d:" << std::endl; boost::fusion::for_each(eig_d, demo::print()); std::cout << std::endl; } 
+1
source

All Articles