2016-11-18 6 views
1

Я пытаюсь найти обходное решение для использования вариативных шаблонов в C++ 03.C++ 03: Шаблоны Variadic с использованием boost

То, что я хотел бы достичь, - в шаблоном классе - был создан атрибут boost::tuple, который будет состоять из вектора для каждого параметра шаблона отдельного класса.

Вот как это будет выглядеть, как с помощью C++ 11 VARIADIC шаблоны:

template<typename ...Parameters> 
class Foo 
{ 
    typedef std::tuple<std::vector<Parameters>...> Vectors_t; 

    Vectors_t _vectorsTuple; 
} 

Я хотел бы добиться того же с помощью наддува :: кортеж и повышение :: MPL или независимо от других возможных способов.

Благодаря

UPDATE

Это окончательное решение, которое я придумал. Частично основано на предложении @stefanmoosbrugger.

template<class TypesList> 
class FooImpl 
{ 
    typedef TypesList TypesList_t; 
    typedef typename boost::mpl::transform < 
     TypesList_t, 
     std::vector<boost::mpl::_1> 
     >::type VectorTypesList_t; 
    typedef typename boost::mpl::reverse_fold< 
     VectorTypesList_t, 
     boost::tuples::null_type, 
     boost::tuples::cons<boost::mpl::_2, boost::mpl::_1> 
     >::type VectorsTuple_t; 

    protected: 
     VectorsTuple_t _vectorsTuple; 
}; 

template<class Type1, 
     class Type2 = boost::mpl::na, 
     class Type3 = boost::mpl::na, 
     class Type4 = boost::mpl::na> /* Made it up to four possible types as an example */ 
class Foo : public FooImpl<boost::mpl::vector<Type1, Type2, Type3, Type4> >{}; 

ответ

2

Вот что-то обходное решение. Я признаю, что это выглядит совершенно уродливо. Но я думаю, что это, по крайней мере, способ, чтобы получить какое-то VARIADIC стиля:

#include <boost/preprocessor/repetition/repeat.hpp> 
#include <boost/preprocessor/repetition/enum_params.hpp> 
#include <boost/preprocessor/repetition/enum_binary_params.hpp> 
#include <boost/preprocessor/arithmetic/inc.hpp> 
#include <boost/preprocessor/cat.hpp> 
#include <boost/preprocessor/facilities/intercept.hpp> 

#include <boost/tuple/tuple.hpp> 
#include <boost/mpl/vector.hpp> 
#include <boost/mpl/copy.hpp> 

#include <vector> 

#define Foo(...) FooHelper< boost::mpl::vector<__VA_ARGS__> > 

template<class T, class Tuple> 
struct tuple_push_front; 

template<class T, BOOST_PP_ENUM_PARAMS(10, class T)> 
struct tuple_push_front<T, boost::tuple<BOOST_PP_ENUM_PARAMS(10, T)> > { 
    typedef boost::tuple<T, BOOST_PP_ENUM_PARAMS(9, T)> type; 
}; 

template <typename MPLVec> 
struct FooHelper { 
    typedef MPLVec mpl_vec_t; 
    // generate a boost::tuple< std::vector<...>, ... > out of the mpl vector 
    typedef typename boost::mpl::fold<mpl_vec_t, 
     boost::tuple<>, 
     tuple_push_front<std::vector<boost::mpl::_2>, boost::mpl::_1> 
    >::type type; 
}; 

int main() { 
    Foo(int,float,char) test; 
} 

Что она делает это: Существует макрос, который поддерживает VARIADIC аргументов. Этот макрос передает аргументы в mpl::vector. FooHelper принимает mpl::vector<T1,...,Tn> и преобразует его в boost::tuple< std::vector<T1>, ..., std::vector<Tn> >.

Ну, я думаю, это не то, что вы хотите, но, может быть, вы можете использовать его как-то. Я поставил его как ответ, а не как комментарий из-за большого блока кода.

ОБНОВЛЕНИЕ: Если вам не нравится материал препроцессора форсирования, вы можете получить тот же результат с вектором слияния ускорения. Цитата из ускоренного документа: The tuple is more or less a synonym for fusion's vector..

#include <boost/fusion/container.hpp> 
#include <boost/fusion/sequence.hpp> 
#include <boost/mpl/int.hpp> 
#include <boost/mpl/vector.hpp> 

#include <vector> 

#define Foo(...) FooHelper< boost::mpl::vector<__VA_ARGS__> > 

template <typename T> 
struct make_vector { 
    typedef std::vector<T> type; 
}; 

template <typename MPLVec> 
struct FooHelper { 
    typedef MPLVec mpl_vec_t; 
    typedef typename boost::mpl::transform<mpl_vec_t, make_vector<boost::mpl::_1> >::type vector_types; 
    typedef typename boost::fusion::result_of::as_vector<vector_types>::type vectors_t; 
    vectors_t _vectorsTuple; 
}; 

int main() { 
    Foo(int, double, float) x; 
} 
+0

Спасибо, что не так уж плохо :) Любые возможности преобразования из MPL :: вектора текущего кортежа может быть менее уродливой? Нам действительно нужны макросы BOOST_PP_ENUM и пользовательский push_front? Удивительно, если бы это было достигнуто более плавным способом, используя mpl :: transform, а не fold – codeJack

+0

ну, вы могли бы использовать 'mpl :: transform' на' mpl_vec_t' для преобразования элементов из 'Tx' в' std :: vector ', а затем просто создайте из него вектор слияния (' boost :: fusion :: result_of :: as_vector :: type') .. :) определенно выглядят менее уродливыми. –

+0

Не могли бы вы обновить свой код этим решением? :) – codeJack