c++11 tuple实现

实现一个简易版的c++11 tuple。

我使用的编译器是gcc,codeblocks13.12自带的,哪个版本我不熟gcc也没去查。

大致看了下他家的tuple实现,多继承,tuple之上还有2个辅助类,走的是类似loki中GenScatterHierarchy的路子。1092行代码,不是盖的。。。

有些强迫症,不打算用多继承,,虽然并不会实例化来,看着闹心。

只考虑实现到POD类型的基本支持就行了,什么右值之类的我还没看到,就不搞了,仅供参考。

个人觉得tuple保存POD类型值就足够了,泛滥就堕落了。

 单继承版本确实比多继承版本美得多了,可变模板参数真是个好东西。

为了tuple_get只需使用static_cast,tuple是public继承的。当然私有继承更好,只是。。。我想tuple的使用应该没有地方会造成歧义吧。

提供了一个tuuple_get<int>(const tuple&)接口获取指定位置的值。

 

#ifndef HI_MPL_TUPLE_H_INCLUDE
#define HI_MPL_TUPLE_H_INCLUDE

namespace hi {
    using namespace mpl::utils;
  //////////////////////////////////////////////////////////
    template<typename... TList> struct tuple;

    template<> struct tuple<> {};

    typedef tuple<> nulltuple;

    //////////////////////////////////////////////////////////
    template<typename T, typename... TList>
    struct tuple<T, TList...> : public tuple<TList...>
    {
        typedef T value_type;
        typedef tuple<TList...> base_type;
        typedef tuple<T, TList...> this_type;

        tuple(const T& v, const TList&... tails):base_type(tails...),_value(v) {}

        tuple(T&& v, TList&&... tails):base_type(std::move(tails)...), _value(std::forward<T>(v)) {}
        tuple(T&& v, TList&... tails):base_type(std::move(tails)...), _value(std::forward<T>(v)) {}
        tuple(T& v, TList&&... tails):base_type(std::move(tails)...), _value(std::forward<T>(v)) {}

        tuple(const this_type& other):base_type(static_cast<const base_type&>(other)),_value(other._value)
        {}

        tuple(this_type&& other):base_type(std::move(static_cast<base_type&>(other))),_value(std::forward<T>(other._value))
        {}

        const T& head() const { return this->_value; }
        T& head() { 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 nulltuple
    {
        typedef T value_type;
        typedef nulltuple base_type;
        typedef tuple<T> this_type;

        tuple(const T& v):_value(v) {}
        tuple(T&& v):_value(std::forward<T>(v)) {}

        tuple(const this_type& other):_value(other._value) {}

        tuple(this_type&& other):_value(std::forward<T>(other._value)) {}

        const T& head() const { return this->_value; }
        T& head() { 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;
    };


    //////////////////////////////////////////////////////////
    template<unsigned int N, typename... TList> struct tuple_at;

    template<unsigned int N, typename T, typename... TList>
    struct tuple_at< N, tuple<T, TList...> >
    {
        typedef typename tuple_at< N-1, tuple<TList...> >::value_type value_type;
        typedef typename tuple_at< N-1, tuple<TList...> >::tuple_type tuple_type;
    };

    template<typename T, typename... TList>
    struct tuple_at< 0, tuple<T, TList...> >
    {
        typedef T value_type;
        typedef tuple<T, TList...> tuple_type;
    };

    template<>
    struct tuple_at<0, nulltuple>
    {
        typedef nulltuple value_type;
        typedef nulltuple tuple_type;
    };

    //////////////////////////////////////////////////////////
    template<unsigned int N, typename... TList>
    constexpr const typename tuple_at<N, tuple<TList...> >::value_type&
    tuple_get(const tuple<TList...>& tuple_)
    {
        typedef tuple<TList...> tuple_type;
        typedef typename tuple_at<N, tuple_type>::tuple_type base_tuple_type;

        return static_cast<const base_tuple_type&>(tuple_).head();
    }

    template<unsigned int N, typename... TList>
    typename tuple_at<N, tuple<TList...> >::value_type&
    tuple_get(tuple<TList...>& tuple_)
    {
        typedef tuple<TList...> tuple_type;
        typedef typename tuple_at<N, tuple_type>::tuple_type base_tuple_type;

        return static_cast<base_tuple_type&>(tuple_).head();
    }
}
#endif

 

例子:

#include "TypeTuple.h"
#include <tuple>

int main()
{
    bool b;
    tuple<int, float, char> pp = {10, 0.1234, 'a'};
    b = std::is_same<tuple_at<2, tuple<int, float, char>>::value_type, char >::value;
    std::cout << "is same: " << b << std::endl;
    b = std::is_same<tuple_at<2, tuple<int, float, char>>::tuple_type, tuple<char> >::value;
    std::cout << "is same: " << b << std::endl;
    std::cout << tuple_get<0>(pp)<<" "<< tuple_get<1>(pp) <<" "<<tuple_get<2>(pp) << std::endl;
    std::tuple<int, float, char> cc{10, 0.1234, 'a'};
    std::cout << sizeof(pp) << "  " << sizeof(cc) << std::endl;
    tuple<int, float, char> ppc = pp;
    std::cout << tuple_get<0>(ppc)<<" "<< tuple_get<1>(ppc) <<" "<<tuple_get<2>(ppc) << std::endl;
    return 0;
}

 

相关推荐:

Python tuple 不可变性的设计意义

tuple不可变因其设计为值语义容器,保证身份与内容绑定、哈希稳定及优化可能;但仅浅层不可变,内部可变对象仍可修改。 为什么tuple不能改,但list可以? 因为tuple在Python里被设计成「值语义」的容器,类似整数或字符串——你不会指望42+=1改掉数字42本身,同理(1,2)一旦创建,它...

Python tuple 不可变性的设计价值

tuple的不可变性是语义契约而非限制,确保内容创建后不被篡改,支撑哈希、线程安全与内存优化;其不可变仅限直接元素引用,不递归约束内部对象状态。 为什么tuple的不可变性不是限制而是契约 Python中tuple的不可变性不是为了“禁止修改”,而是向调用方和解释器明确传递一个语义承诺:这个对象的内...

Python tuple 不可变的设计价值

tuple被设计成不可变是为了保障哈希性、线程安全和内存紧凑这三类刚性需求;其自身结构不可变但可包含可变对象,外层冻结而内层自由,体现为接口契约而非限制。 为什么tuple被设计成不可变 因为tuple的核心定位是「数据容器」而非「数据操作载体」——它要承担哈希性、线程安全、内存紧凑这三类刚性需求,...

Python 如何让一个类支持解包赋值(像 tuple 那样)

__iter__是最直接有效的方案,因为解包依赖迭代协议而非序列协议,只需返回迭代器即可支持解包,语义明确且可控,避免__getitem__带来的序列语义误导。 为什么__iter__是最直接有效的方案 Python的解包赋值(如a,b=obj)底层依赖的是迭代协议,不是序列协议。也就是说,只要对象...

Python tuple 为什么比 list 更省内存?

tuple比list更省内存,因其无扩容预留、无allocated字段、对象头更轻量,且字面量可编译期复用并缓存哈希值;sys.getsizeof显示小32–40字节。 因为tuple是不可变对象,Python可以在创建时就确定其内存布局,省去list需要预留扩容空间、维护长度/引用计数等额外字段的...

Python tuple 为什么不可变?

Python中tuple不可变的根本原因在于其设计目标是作为不可变序列容器,内存布局固定、支持哈希、语义上表达不变性;但仅保证引用不可变,内部可变对象内容仍可修改。 Python中的tuple不可变,根本原因在于它的设计目标和底层实现方式——它被定义为一种**不可变的序列容器**,用于表达“固定不变...

C++11标准库tuple模板怎么使用

这篇文章主要讲解了“C++11标准库tuple模板怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++11标准库tuple模板怎么使用”吧!什么是tuple作者英语一般,在写文章之前首先查了一下tuple的意思,百度翻译给出的结果是:元组,数...

list+tuple的基础及操作

列表(list)基础及基础操作+tuple的小范围知识list一个排列有序的线性结构队列,由若干个元素组成(元素可以是任意对象)列表是可变类型list():newempty(空)listlist(iterable):newlistinitializedfrom'sitemsiterable:可迭代对...