Как показывают другие ответы, возможно добиться желаемого поведения (МНОГО) ускоренного метапрограммирования. Используя ответы на эти вопросы: Препроцессор C ++: избегать повторения кода в списке переменных членов , Итерировать по элементам Struct и Class * Я что-то скомбинировал, который перебирает все отражаемые элементы двух контейнеров и присваиваетих после кастинга.
Однако я не знаю, насколько надежен этот подход, и, вероятно, не рекомендовал бы использовать его в рабочем коде.
#include <boost/preprocessor.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/bind.hpp>
#define REM(...) __VA_ARGS__
#define EAT(...)
#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)
#define DETAIL_TYPEOF(...) DETAIL_TYPEOF_HEAD(__VA_ARGS__)
#define DETAIL_TYPEOF_HEAD(x, ...) REM x
#define DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__),
#define STRIP(x) EAT x
#define PAIR(x) REM x
template<class M, class T>
struct make_const
{
typedef T type;
};
template<class M, class T>
struct make_const<const M, T>
{
typedef typename boost::add_const<T>::type type;
};
#define REFLECTABLE(...) \
static const int fields_n = BOOST_PP_VARIADIC_SIZE(__VA_ARGS__); \
friend struct reflector; \
template<int N, class Self> \
struct field_data {}; \
BOOST_PP_SEQ_FOR_EACH_I(REFLECT_EACH, data, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
#define REFLECT_EACH(r, data, i, x) \
PAIR(x); \
template<class Self> \
struct field_data<i, Self> \
{ \
Self & self; \
field_data(Self & self) : self(self) {} \
\
typename make_const<Self, TYPEOF(x)>::type & get() \
{ \
return self.STRIP(x); \
}\
typename boost::add_const<TYPEOF(x)>::type & get() const \
{ \
return self.STRIP(x); \
}\
const char * name() const \
{\
return BOOST_PP_STRINGIZE(STRIP(x)); \
} \
}; \
struct reflector
{
//Get field_data at index N
template<int N, class T>
static typename T::template field_data<N, T> get_field_data(T& x)
{
return typename T::template field_data<N, T>(x);
}
// Get the number of fields
template<class T>
struct fields
{
static const int n = T::fields_n;
};
};
// Custom code for struct assignment below here
struct dual_field_visitor
{
template<class CA, class CB, class Visitor, class T>
void operator()(CA & ca, CB & cb, Visitor v, T)
{
v(reflector::get_field_data<T::value>(ca), reflector::get_field_data<T::value>(cb));
}
};
template<class CA, class CB, class Visitor>
void dual_visit_each(CA & ca, CB & cb, Visitor v)
{
typedef boost::mpl::range_c<int,0,reflector::fields<CA>::n> range;
boost::mpl::for_each<range>(boost::bind<void>(dual_field_visitor(), boost::ref(ca), boost::ref(cb), v, _1));
}
struct assign_visitor
{
template<class FieldDataA, class FieldDataB>
void operator()(FieldDataA fa, FieldDataB fb)
{
fa.get() = static_cast<std::decay_t<decltype(fa.get())>>(fb.get());
}
};
template<typename T>
struct Container
{
REFLECTABLE
(
(T) a,
(T) b
)
template<typename U>
Container & operator=(const Container<U> & c)
{
dual_visit_each(*this, c, assign_visitor());
return *this;
}
Container & operator=(const Container & c)
{
if(this != & c)
{
dual_visit_each(*this, c, assign_visitor());
}
return *this;
}
};
int main()
{
Container<int> a {1, 2};
Container<float> b {3.0f, 4.0f};
Container<float> c {5.0f, 6.0f};
a = b;
b = c;
return 0;
}