【发布时间】:2018-11-22 09:43:02
【问题描述】:
我想编写一个模板函数,它遍历std::pair 的容器并返回一个模板化值,其中包含这对中的两种类型。我已经为std::map 工作,如下所示:
template <typename T1, typename T2>
std::pair<std::vector<T1>, std::vector<T2>> unzip(const std::map<T1,T2>& zipped)
{
auto unzipped = std::make_pair(std::vector<T1>(), std::vector<T2>());
for (auto& one_two : zipped)
{
unzipped.first.push_back(one_two.first);
unzipped.second.push_back(one_two.second);
}
return unzipped;
}
这很好用,但它将容器限制为std::map。我想要完成的是让这也适用于std::vector<std::pair<T1,T2>> 之类的东西,因为两个容器的迭代工作方式相同。
我尝试通过更改模板参数使容器成为模板:
template <typename T1, typename T2, template<typename ... Types> class Container>
std::pair<std::vector<T1>, std::vector<T2>> unzip(const Container<T1,T2>& zipped)
{
//do stuff and return
}
但在这种情况下,如果不使用std::map,则推论会失败,因为std::vector 仅依赖于单一类型。然后我尝试变得更有创意,但编译器抱怨得更多:
template <typename PairContainerType>
std::pair<std::vector<typename PairContainerType::value_type::first_type>,
std::vector<typename PairContainerType::value_type::second_type>>
unzip(const PairContainerType& zipped)
{
typedef typename PairContainerType::value_type::first_type T1;
typedef typename PairContainerType::value_type::second_type T2;
//do the same stuff and return
}
我认为我正在尝试做的事情应该是可能的,但我不知所措。如果这很重要,我正在使用c++11,但如果我想要的东西在未来的版本中可用,我仍然对这些解决方案感兴趣。谢谢。
更新: 感谢 RiaD,我得到了以下使用 c++11 的工作:
template <typename PairContainerType,
typename T1 = typename std::remove_const<typename PairContainerType::value_type::first_type>::type,
typename T2 = typename std::remove_const<typename PairContainerType::value_type::second_type>::type>
std::pair<std::vector<T1>, std::vector<T2>> unzip(const PairContainerType& zipped)
{
//do stuff and return
}
请注意,它与接受的答案略有不同,因为它使用std::remove_const 而不是std::remove_const_t,并且需要在末尾添加::type。
RiaD 还指出,模板类型 T1 和 T2 可以被拨打电话的人覆盖。正如 Jarod42 所建议的,这可以通过一些额外的输入来缓解,这让我留在了最终的 c++11 解决方案中:
template <typename PairContainerType>
std::pair<std::vector<typename std::remove_const<typename PairContainerType::value_type::first_type>::type>,
std::vector<typename std::remove_const<typename PairContainerType::value_type::second_type>::type>>
unzip(const PairContainerType& zipped)
{
auto unzipped = std::make_pair(
std::vector<typename std::remove_const<typename PairContainerType::value_type::first_type>::type>(),
std::vector<typename std::remove_const<typename PairContainerType::value_type::second_type>::type>());
for (const auto& one_two : zipped)
{
unzipped.first.push_back(one_two.first);
unzipped.second.push_back(one_two.second);
}
return unzipped;
}
总的来说,c++14 和 c++17 看起来很吸引人。我本可以使用 auto 返回功能节省自己的时间!
【问题讨论】:
标签: c++ c++11 templates variadic-templates template-templates