代码之家  ›  专栏  ›  技术社区  ›  Arzar

元组兼容C++ 0x变量模板吗?

  •  5
  • Arzar  · 技术社区  · 15 年前

    我在玩可变模板(GCC4.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');
    }
    

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

    如果我替换每一次 boost::tuple 通过 std::tuple ,编译得很好。
    boost元组实现有问题吗?或者这是一个gcc错误?

    我现在必须坚持Boost.Tuple。你知道什么解决办法吗?
    谢谢。

    1 回复  |  直到 15 年前
        1
  •  7
  •   UncleBens    15 年前

    它似乎不喜欢扩张 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');
    }