在C++ 11中将(1元组到10元组)参数转换为n元组参数

kfm*_*e04 2 c++ tuples variadic-templates c++11

可能重复:
Pretty-print std :: tuple

在数据库库(soci)中,下面有一大块代码可以处理std::tuple<>一到十个参数.

静态类方法from_base(),to_base()用于1元组到10元组的参数.

guts基本上将每个n元组元素传入传入的流中.一切都是硬编码的.

如何将此代码转换为使用C++ 11的可变参数模板(参数没有限制)? 实际上使用可变参数模板是次要的.我们真正想做的是用n-tuple参数的一般情况替换硬编码.

部分问题是,从技术上讲,只有一个参数,但该参数是一个n元组,所以我不能完全使用维基百科中的描述.什么是最好的方法?

#include "values.h"
#include "type-conversion-traits.h"
#include <tuple>

namespace soci
{

template <typename T0>
struct type_conversion<std::tuple<T0> >
{
    typedef values base_type;

    static void from_base(base_type const & in, indicator ind,
        std::tuple<T0> & out)
    {
        in
            >> std::get<0>(out);
    }

    static void to_base(std::tuple<T0> & in,
        base_type & out, indicator & ind)
    {
        out
            << std::get<0>(in);
    }
};

template <typename T0, typename T1>
struct type_conversion<std::tuple<T0, T1> >
{
    typedef values base_type;

    static void from_base(base_type const & in, indicator ind,
        std::tuple<T0, T1> & out)
    {
        in
            >> std::get<0>(out)
            >> std::get<1>(out);
    }

    static void to_base(std::tuple<T0, T1> & in,
        base_type & out, indicator & ind)
    {
        out
            << std::get<0>(in)
            << std::get<1>(in);
    }
};

// ... all the way up to 10 template parameters

}
Run Code Online (Sandbox Code Playgroud)

RUNNABLE ANSWER(基于Grizzly的帖子)

#include <iostream>
#include <tuple>

using namespace std;

// -----------------------------------------------------------------------------

template<unsigned N, unsigned End>
struct to_base_impl 
{
    template<typename Tuple>
    static void execute(Tuple& in, ostream& out) 
    {
      out << std::get<N>(in) << endl;
      to_base_impl<N+1, End>::execute(in, out);
    }
};

template<unsigned End>
struct to_base_impl<End, End>
{ 
    template<typename Tuple>
    static void execute(Tuple& in, ostream& out) 
    {
      out << "<GAME OVER>" << endl;
    }
};

// -----------------------------------------------------------------------------

template <typename Tuple>
struct type_conversion
{
    static void to_base(Tuple& in, ostream& out )
    {
        to_base_impl<0, std::tuple_size<Tuple>::value>::execute(in, out);
    }
};

template <typename... Args>
struct type_conversion<std::tuple<Args...>>
{
    static void to_base(std::tuple<Args...>& in, ostream& out )
    {
        to_base_impl<0, sizeof...(Args)>::execute(in, out);
    }
};

// -----------------------------------------------------------------------------

main()
{
    typedef tuple<double,int,string> my_tuple_type;
    my_tuple_type t { 2.5, 5, "foo" };

    type_conversion<my_tuple_type>::to_base( t, cerr );
}
Run Code Online (Sandbox Code Playgroud)

Gri*_*zly 5

如果我正确理解你的问题,你基本上需要分别调用运算符<<或者>>你的元组的每个元素.在这种情况下,你可以使用部分特化和递归来构造类似于for循环的东西(排序,因为它实际上每次调用一个不同的函数):

template<unsigned N, unsigned End>
struct to_base_impl {
    template<typename Tuple>
    void execute(Tuple& in, base_type& out) {
      out<<std::get<N>(in);
      to_base_impl<N+1, End>::execute(in, out);
    }
};

template<unsigned End>
struct to_base_impl<End, End> { //End of loop
    template<typename Tuple>
    void execute(Tuple& in, base_type& out) {}
};

template <typename Tuple>
struct type_conversion
{
    typedef values base_type;

    static void to_base(Tuple& in, base_type & out, indicator & ind){
        to_base_impl<0, std::tuple_size<Tuple>::value>::execute(in, out);
    }
};
Run Code Online (Sandbox Code Playgroud)

这将从零迭代到元组的大小并调用out<<std::get<N>(in);每次迭代.from_base将以相同的方式实现in>>std::get<N>(out);.如果要确保仅使用元组调用转换器,可以使用可变参数模板:

template <typename... Args>
struct type_conversion<std::tuple<Args...>>
{
    typedef values base_type;

    static void to_base(std::tuple<Args...>& in, base_type & out, indicator & ind){
        to_base_impl<0, sizeof...(Args)>::execute(in, out);
    }
};
Run Code Online (Sandbox Code Playgroud)

当然你可以更一般地写这个,但是这会使源变得更复杂,并且可能不会给你太多回报.