首页 > 解决方案 > c++ 中没有 std::tuple 的 std::iterator 有什么原因吗?

问题描述

std::iterator有一个for似乎很自然std::tuple。但是它没有实现,所以程序员实现了自己的版本。例如,可以在Jonathan Müller 的博客中找到一个。

我忽略了什么吗?tuple_iterator 没有“官方版本”有什么原因吗?

标签: c++iteratortuples

解决方案


std::tuple不是容器,至少在标准库容器的意义上不是。它不能用通常的方法迭代,因为它包含不同类型的对象。标准容器是同构容器,而标准容器是std::tuple异构容器。

这并不意味着你不能迭代一个元组,但它非常麻烦并且你不能使用已建立的语法:

让我们假设您想以与迭代容器相同的方式迭代元组,例如std::vector

std::tuple<int, std::string, bool> t = {...};

for (auto it = t.begin(); it != t.end(); ++it)
{
    auto elem = *it; // this cannot work the same way as with containers
                     // because each element is of a different type
}

你可以做几件事。使用std::variant包含容器类型的迭代器。访问下面的真实对象并不容易。而且这种迭代器也不能在标准库中需要迭代器的其他任何地方使用,至少在没有一些额外工作的情况下不能使用。

还有一项关于元编程(反射,内省)的提案的工作,该提案具有(或曾经,未遵循)以下语法:

std::tuple<int, std::string, bool> t = {...};

// something like this (can't remember the syntax exactly):
for constexpr ... (auto elem : t)
{
    // only the common set of operations permitted with `elem`
    // e.g. this is valid
    std::cout << elem << std::endl;

    // this is invalid:
    //elem.size();
}

这实际上会在编译时展开,从而产生以下代码:

std::tuple<int, std::string, bool> t = {...};

{
    int elem = std::get<0>(t);
    std::cout << elem << std::endl;
}
{
    std::string elem = std::get<1>(t);
    std::cout << elem << std::endl;
}
{
    bool elem = std::get<2>(t);
    std::cout << elem << std::endl;
}

推荐阅读