如何编写适用于地图和矢量对的c ++模板>

jon*_*lpy 10 c++ templates template-templates variadic-templates c++11

我想编写一个模板函数,它迭代一个容器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;
}
Run Code Online (Sandbox Code Playgroud)

这很好,但它限制了容器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
}
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,如果不使用,则扣除失败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
}
Run Code Online (Sandbox Code Playgroud)

我想我应该做的事情应该是可能的,但我不知所措.我正在使用,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
}
Run Code Online (Sandbox Code Playgroud)

请注意,它与接受的答案略有不同,因为它使用std::remove_const而不是std::remove_const_t并且需要::type在最后添加.

里亚德还指出,模板类型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;
}
Run Code Online (Sandbox Code Playgroud)

总的来说,c ++ 14和c ++ 17看起来非常吸引人.我可以用auto返回功能节省时间!

Ria*_*iaD 10

通常用c ++你只允许任何类型,如果它不正确就让它失败.要获得T1和T2你可能会得到收集VALUE_TYPE(中都存在std::map,并std::vector<std::pair<>>和其他人如std::set<std::pair<>>)

template <typename T, typename T1 = std::remove_const_t<typename T::value_type::first_type>, typename T2 = std::remove_const_t<typename T ::value_type::second_type>>
std::pair<std::vector<T1>, std::vector<T2>> unzip(const T& 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;
}
Run Code Online (Sandbox Code Playgroud)

它有(轻微的)缺点,有人可能会强制T1和T2.您可以从模板参数列表中删除它们.

template <typename T>
auto /* or return type (but it will require copy-pasting) before c++14*/ 
unzip(const T& zipped)
{
    using T1 = std::remove_const_t<typename T::value_type::first_type>; //may need to remove const
    using T2 = std::remove_const_t<typename T::value_type::second_type>; 
    // impl
}
Run Code Online (Sandbox Code Playgroud)

需要删除const,因为value_type std::mapstd::pair<const K, V>.std::remove_const_t如果你需要较旧的标准支持,例如你需要的c ++ 11,它可以不用typename std::remove_const<>::type