说说 std::tuple 的一个实现


#1
#include <iostream>

template<typename ...Args> struct tuple;  // 定义
template<> struct tuple<> {};              // 定义空参数, 用于模板递归的终点 
template<typename T, typename... Args>
struct tuple<T, Args...> : public tuple<Args...>
{
    typedef T value_type;
    typedef tuple<Args...> base_type;
    typedef tuple<T, Args...> this_type;
    tuple(const T& v, const Args&... tails) :base_type(tails...), _value(v) {}
    tuple(const this_type& other) :base_type(static_cast<const base_type&>(other)), _value(other._value)
    {}
    const T& value() const {
        return this->_value;
    }
    T& value() {
        return this->_value;
    }
    this_type& operator=(const this_type& other)
    {
        base_type::operator=(static_cast<const base_type&>(other));
        _value = other._value;
        return *this;
    }
    this_type& operator=(this_type&& other)
    {
        base_type::operator=(std::move(static_cast<base_type&>(other)));
        _value = other._value;
        return *this;
    }
protected:
    T _value;
};
// 模板展开终点
template<typename T>
struct tuple<T> : public tuple<>
{
    typedef T value_type;
    typedef tuple<> base_type;
    typedef tuple<T> this_type;
    tuple(const T& v) :_value(v) {}
    tuple(const this_type& other) :_value(other._value) {}
    const T& value() const { return this->_value; }
    T& value() { return this->_value; }
    this_type& operator=(const this_type& other)
    {
        _value = other._value;
        return *this;
    }
    this_type& operator=(this_type&& other)
    {
        _value = other._value;
        return *this;
    }
protected:
    T _value;
};
// type traits , 通过模板开展,确定对应索引的数据类型
template<unsigned int N, typename ...Args> struct tuple_type_traits;
template<unsigned int N, typename T, typename ...Args>
struct tuple_type_traits< N, tuple<T, Args...> >
{
    typedef typename tuple_type_traits<N - 1, tuple<Args...>>::value_type value_type;
    typedef typename tuple_type_traits<N - 1, tuple<Args...>>::tuple_type tuple_type;
};
template<typename T, typename ...Args>
struct tuple_type_traits<0, tuple<T, Args...>>
{
    typedef typename T value_type;
    typedef typename tuple<T, Args...> tuple_type;
};
template<>
struct tuple_type_traits<0, tuple<>>
{
    typedef tuple<> value_type;
    typedef tuple<> tuple_type;
};
// 获取对应索引的值
template<unsigned int N, typename ...Args>
constexpr const typename tuple_type_traits<N, tuple<Args...> >::value_type&
tuple_get(const tuple<Args...>& tuple_)
{
    typedef tuple<Args...> tuple_type;
    typedef typename tuple_type_traits<N - 1, tuple_type>::tuple_type base_tuple_type;
    return static_cast<const base_tuple_type&>(tuple_).value();
}
template<typename ...Args>
constexpr const typename tuple_type_traits<0, tuple<Args...> >::value_type&
tuple_get(const tuple<Args...>& tuple_)
{
    typedef tuple<Args...> tuple_type;
    typedef typename tuple_type_traits<N - 1, tuple_type>::tuple_type base_tuple_type;
    return static_cast<const base_tuple_type&>(tuple_).value();
}
template<unsigned int N, typename... Args>
typename tuple_type_traits<N, tuple<Args...> >::value_type&
tuple_get(tuple<Args...>& tuple_)
{
    typedef tuple<Args...> tuple_type;
    typedef typename tuple_type_traits<N, tuple_type>::tuple_type base_tuple_type;
    return static_cast<base_tuple_type&>(tuple_).value();
}
// 获取 tuple 的大小
template <typename ...Args> struct tuple_size;       
template<typename ...Args>
struct tuple_size<tuple<Args...>>
{
    static const std::size_t value = sizeof ...(Args);
};
int main()
{
    /* tuple<float, int, double> 对象最终的结构
    t1<float, int, double>
    |---t1<int, double>
    |-------t1<double>
    |----------t1<>
    */
    tuple<float, int, double> t1 = {1.0f, 2, 3.0};
    /*
    获取对应的 tuple 大小
    */
    std::size_t t2 = tuple_size<tuple<float, int, double>>::value;
    /*
    获取类型
    这里通过模板的递归展开, 传入 tuple_type_traits 以后首先进入
    template<unsigned int N, typename T, typename ...Args>
        struct tuple_type_traits< N, tuple<T, Args...> >
    由于我们的偏特化
    template<typename T, typename ...Args>
        struct tuple_type_traits<0, tuple<T, Args...>>
    因此在 N != 0 的情况下, 模板将会递归展开, 知道 N == 0, 而这个递归的过程中,实际上就是在递归推导 tuple<float, int, double> 的父类
    最终 N == 0 的情况下, 就得到了 tuple_type_traits<0, tuple<T, Args...>>::tuple_type, 这个时候 tuple_type 就是对应 tuple<float, int, double> 一个父类的类型。
    
    举个例子: 假设 N == 2, 会经过3次推导, 直到 N == 0
    推导第一步:    tuple_type_traits<2, tuple<float, Args...>>
    推导第二步:    tuple_type_traits<1, tuple<int, Args...>>
    推导第三步:    tuple_type_traits<0, tuple<double>>, 此时 N == 0
    由于偏特化到达我们设定的终点, 产生了真正的类型定义
    typedef typename double value_type;
    typedef typename tuple<double> tuple_type;
    */
    bool b1 = std::is_same<tuple_type_traits<0, tuple<float, int, double>>::value_type, float>::value;
    bool b2 = std::is_same<tuple_type_traits<1, tuple<float, int, double>>::value_type, int>::value;
    bool b3 = std::is_same<tuple_type_traits<2, tuple<float, int, double>>::value_type, double>::value;
    bool b4 = std::is_same<tuple_type_traits<0, tuple<float, int, double>>::tuple_type, tuple<float, int, double>>::value;
    bool b5 = std::is_same<tuple_type_traits<1, tuple<float, int, double>>::tuple_type, tuple<int, double>>::value;
    bool b6 = std::is_same<tuple_type_traits<2, tuple<float, int, double>>::tuple_type, tuple<double>>::value;
    /*
    获取对应的 tuple 值
    由于我们通过  tuple_type_traits 获取到 tuple 的真正类型, 因此我们这里实际上就是通过 static_cast<tuple<...Args>> 从一个子类转为父类,再获取对应的value
    */
    float t3 = tuple_get<0>(t1);
    int t4 = tuple_get<1>(t1);
    double t5 = tuple_get<2>(t1);
    return 0;
}