具有相同索引元素的元组的向量;确定向量的大小是否相同



我希望创建一个向量,存储来自不同向量的相同索引元素的元组。虽然我能够实现它,有一个警告,如果调用者传入不同大小的向量,我想知道是否有一种方法来确定是否所有传入的向量都是相同的大小。

template <typename... Args>
std::vector<std::tuple<Args...>> Foo(const std::vector<Args>&... vecs) 
{
std::vector<std::tuple<Args...>> result;
const auto elems = sizeof...(vecs);
std::cout << "Elems = " << elems << std::endl;
for (size_t i = 0; i < elems; ++i) 
{
result.emplace_back(std::make_tuple(vecs[i]...));
}
return result;
}
vector<int> v1 = {1, 4, 8};
vector<double> v2 = {1.1, 4.1, 8.1};
auto vec1 = Foo(v1, v2); // { {1, 1.1}, {4, 4.1}, {8, 8.1} }

显示的代码无论如何都不能像预期的那样工作。sizeof...给出包中参数的数量,而不是包中单个元素的大小。

可能像这样(假设c++ 17或更高版本):

template <typename Arg1, typename... Args>
std::vector<std::tuple<Arg1, Args...>> Foo(const std::vector<Arg1>& vec1, const std::vector<Args>&... vecs) 
{
if(((vec1.size() != vecs.size()) || ...))
throw std::invalid_argument("All arguments to Foo must have equal length.");
std::vector<std::tuple<Arg1, Args...>> result;
for (size_t i = 0; i < vec1.size(); ++i) 
{
// emplace_back is pointless if you use don't pass
// the constructor arguments directly
// Also make_tuple doesn't always produce tuple<Args...>.
result.emplace_back(vec1[i], vecs[i]...);
}
return result;
}

但是我会考虑您是否真的需要将此函数限制为std::vector。您可以接受任何范围并从c++ 20中的std::range_value_t中确定元组类型,或者接受迭代器对并从解引用迭代器中确定元组类型。

你也可以考虑让函数完全转发是否有意义。

如果允许实参列表为空,则结果向量的大小存在歧义。在这种情况下,我建议添加一个特定的重载处理方法。