BOOST_FUSION_ADAPT_TPL_STRUCT и размер массива шаблона

Я пытаюсь перебрать структуру шаблона C ++ благодаря BOOST_FUSION_ADAPT_TPL_STRUCT. Моя структура содержит многомерные массивы фиксированного размера, размеры которых являются параметрами шаблона. Если мы рассмотрим пример Boost, модифицированный под мою проблему:

#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;
}

Компиляция не удалась. Более того, он также не будет работать, если мы добавим только целочисленный параметр шаблона, даже не используя его для размера массива.

Это возможно даже с BOOST_FUSION_ADAPT_TPL_STRUCT? Если нет, как я должен идти об этом?

4

Решение

От доктор:

Последовательность (template_param0) (template_param1) … объявляет имена параметры типа шаблона используемый.

Пока у вас есть нетипичный параметр шаблона SIZE:

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

Вы можете преобразовать его в тип параметра шаблона и использовать boost::mpl::int_ как обертка для переноса размера.

Теперь ваш код скомпилированный.

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

Другие решения

После долгого разговора с Евгением Панасюком я закончил чем-то другим. Поскольку я хотел иметь возможность выполнять некоторые простые арифметические операции над структурами данных, я решил использовать Eigen::Map скорее, чем Boost::multi_array так как он предлагает широкий спектр операторов, а также четкую документацию.

Таким образом, цикл более высокого уровня обрабатывается boost::fusion::for_each и петли нижнего уровня обрабатываются Eigen. Массивы отображаются линейно на собственные векторы. Размеры передаются в data_eigenконструктор.

#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

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector