Goo*_*ofy 26 c++ tuples std c++11
我想知道在C++ 0x的标准库中如何实现元组.我试着阅读libstdc ++手册中的描述,然后阅读模板列表,但是很难理解它是如何工作的,特别是在阅读代码时.
有人能用几句话解释我的元组实现的想法吗?我想知道这一点,因为我想在我的代码中使用元组,我想了解它是如何工作的以及它带来了什么类型的开销(仅扩展编译时间,对内存执行许多复制操作,在构造函数中执行许多其他函数)等).
mit*_*ull 27
实现元组的一种方法是使用多重继承.元组元素由叶类保存,元组类本身继承自多个叶子.在伪代码中:
template<typename T0, typename T1, ..., typename Tn>
class PseudoTuple : TupleLeaf<0, T0>, TupleLeaf<1, T1>, ..., TupleLeaf<n, Tn> {
...
};
Run Code Online (Sandbox Code Playgroud)
每个叶子都有一个索引,因此即使它们包含的类型相同,每个基类也会变得唯一,所以我们可以使用简单的static_cast 访问第n个元素:
static_cast<TupleLeaf<0, T0>*>(this);
// ...
static_cast<TupleLeaf<n, Tn>*>(this);
Run Code Online (Sandbox Code Playgroud)
我在这里写了关于这个"扁平"元组实现的详细解释:C++ 11元组实现细节(第1部分)
mir*_*irk 11
元组通常实现为编译时链接列表.
代码通过模板语法有点混淆,但通常存在以下元素:
在C++ 03中存在合理的实现(例如,boost).
如Motti所述,可变参数模板允许无限数量的元素.
成本通常是编译时间一.在初始化期间(最大1)可以调用复制构造函数,并且在复制元组本身时也可以调用复制构造函数.
我以为我会添加一个非伪代码的简单递归实现以供参考
#include <iostream>
// Contains the actual value for one item in the tuple. The
// template parameter `i` allows the
// `Get` function to find the value in O(1) time
template<std::size_t i, typename Item>
struct TupleLeaf {
Item value;
};
// TupleImpl is a proxy for the final class that has an extra
// template parameter `i`.
template<std::size_t i, typename... Items>
struct TupleImpl;
// Base case: empty tuple
template<std::size_t i>
struct TupleImpl<i>{};
// Recursive specialization
template<std::size_t i, typename HeadItem, typename... TailItems>
struct TupleImpl<i, HeadItem, TailItems...> :
public TupleLeaf<i, HeadItem>, // This adds a `value` member of type HeadItem
public TupleImpl<i + 1, TailItems...> // This recurses
{};
// Obtain a reference to i-th item in a tuple
template<std::size_t i, typename HeadItem, typename... TailItems>
HeadItem& Get(TupleImpl<i, HeadItem, TailItems...>& tuple) {
// Fully qualified name for the member, to find the right one
// (they are all called `value`).
return tuple.TupleLeaf<i, HeadItem>::value;
}
// Templated alias to avoid having to specify `i = 0`
template<typename... Items>
using Tuple = TupleImpl<0, Items...>;
int main(int argc, char** argv) {
Tuple<int, float, std::string> tuple;
Get<0>(tuple) = 5;
Get<1>(tuple) = 8.3;
Get<2>(tuple) = "Foo";
std::cout << Get<0>(tuple) << std::endl;
std::cout << Get<1>(tuple) << std::endl;
std::cout << Get<2>(tuple) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)