std::tuple 实现原理以及反序存储
Link Share :https://zhiqiang.org/coding/std-tuple.html
- via RSS
std::tuple
的原理并不复杂,但有些细节非常有意思。其中有一个是至少在gnu C++ std
的实现中,std::tuple
是倒序存储的:
std::tuple<int, int> ii;
std::cout << (&std::get<0>(ii)) < (&std::get<1>(ii)) << std::endl; // output false
很多人都以为它就是下面这样简单实现的:
template<typename Head, ...typename Tail>
my::tuple : private my::tuple<...Tail> {
Head head;
};
但这个实现有个问题,空类也会占用一个字节的空间!这和std::tuple
的实际表现不符。具体可以参考下面代码:
struct Empty { };
int main() {
std::cout << sizeof(std::tuple<double, Empty>) << std::endl; // 8
std::cout << sizeof(my::tuple<double, Empty>) << std::endl; // 16
}
为了达到省去空类的占用空间,std::tuple
的所有成员都是继承出来的。这利用了 C++的一个特性:继承空类不会增加子类的空间。
template<std::size_t _Idx, typename _Head, typename... _Tail>
struct _Tuple_impl<_Idx, _Head, _Tail...>
: public _Tuple_impl<_Idx + 1, _Tail...>, private _Head_base<_Idx, _Head>
{ }
template<typename... _Elements>
class tuple : public _Tuple_impl<0, _Elements...>
{ }
也就是说std::tuple<int, double, char>
基本相当于:
std::tuple<int, double, char>
: private _Head_base<2, char>, private _Head_base<1, double>, private _Head_base<0, int>
{}
而_Head_base
只是对元素的一个简单封装:
template<std::size_t _Idx, typename _Head>
struct _Head_base<_Idx, _Head, false> {
_Head value;
};
但它对空类做了一个特殊处理,使得封装后还是空类(注意上面的实现并没有得到空类):
template<std::size_t _Idx, typename _Head, bool = __empty_not_final<_Head>::value>
struct _Head_base;
// 此时 _Head 为空类。
template<std::size_t _Idx, typename _Head>
struct _Head_base<_Idx, _Head, true> : public _Head
{ }
由此可见,std::tuple
的确是倒序存储的。但为什么它要这么做呢?【待续】
Tips: Until now, everytime you want to store your article, we will help you store it in Filecoin network. In the future, you can store it in Filecoin network using your own filecoin.
Support author:
Author's Filecoin address:
Or you can use Likecoin to support author: