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;
}