Совместим ли Boost.Tuple с вариабельными шаблонами C ++ 0x? - PullRequest
5 голосов
/ 25 апреля 2010

Я играл с вариадическими шаблонами (gcc 4.5) и столкнулся с этой проблемой:

template <typename... Args>
boost::tuple<Args...>
my_make_tuple(Args... args)
{
   return boost::tuple<Args...>(args...);
}

int main (void)
{
    boost::tuple<int, char> t = my_make_tuple(8, 'c');
}

Сообщение об ошибке GCC:

sorry, unimplemented: cannot expand 'Arg ...' into a fixed-length argument list
In function 'int my_make_tuple(Arg ...)'

Если я заменим каждое вхождение boost::tuple на std::tuple, оно будет отлично скомпилировано.
Есть ли проблема в реализации Boost Tuple? Или это ошибка GCC?

Сейчас я должен придерживаться Boost.Tuple. Знаете ли вы какой-нибудь обходной путь?
Спасибо.

1 Ответ

7 голосов
/ 25 апреля 2010

Не похоже, что расширение Args... до T1, T2, T3, ..., T9, как это имеет Boost.

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

#include <boost/tuple/tuple.hpp>

template <typename... Args>
auto my_make_tuple(Args... args) -> decltype(boost::make_tuple(args...))
{
   return {args...};
}

int main (void)
{
    boost::tuple<int, char> t = my_make_tuple(8, 'c');
}

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

#include <boost/tuple/tuple.hpp>

template <unsigned, class, class...> struct nth_argument;

template <unsigned N, class Default, class T, class... Args>
struct nth_argument<N, Default, T, Args...>
{
    typedef typename nth_argument<N - 1, Default, Args...>::type type;
};

template <class Default, class T, class... Args>
struct nth_argument<0, Default, T, Args...>
{
    typedef T type;
};

template <unsigned N, class Default>
struct nth_argument<N, Default>
{
    typedef Default type;
};

template <typename ...Args>
struct tuple_from_var_template
{
    typedef boost::tuple<
        typename nth_argument<0, boost::tuples::null_type, Args...>::type,
        typename nth_argument<1, boost::tuples::null_type, Args...>::type,
        typename nth_argument<2, boost::tuples::null_type, Args...>::type,
        typename nth_argument<3, boost::tuples::null_type, Args...>::type,
        typename nth_argument<4, boost::tuples::null_type, Args...>::type,
        typename nth_argument<5, boost::tuples::null_type, Args...>::type,
        typename nth_argument<6, boost::tuples::null_type, Args...>::type,
        typename nth_argument<7, boost::tuples::null_type, Args...>::type,
        typename nth_argument<8, boost::tuples::null_type, Args...>::type,
        typename nth_argument<9, boost::tuples::null_type, Args...>::type
    > type;
};

template <typename... Args>
typename tuple_from_var_template<Args...>::type my_make_tuple(Args... args)
{
   return typename tuple_from_var_template<Args...>::type(args...);
}

int main (void)
{
    boost::tuple<int, char> t = my_make_tuple(8, 'c');
}
...