我想编写一个模板函数,用于迭代包含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
返回特性来节省时间!
auto
返回类型)。auto
并非必需,只是更加方便(至少对于C++14而言)。 - Jarod42std::pair<std::vector<typename remove_const<typename T::value_type::first_type>::type>, std::vector<typename remove_const<typename T::value_type::second_type>::type>>
(同时重写remove_const
)两次(在返回类型和主体中)。 - Jarod42typename std::remove_const<T::value_type>::type
。std::remove_const
本身是(无关的)类型。 - RiaD