如何声明并定义一个泛型模板的flip_map函数?

编程语言 2026-07-10

我在头文件中有以下内容:

template <typename A, typename B>
pair<B, A> flip_pair(const pair<A, B> &);
template <typename A, typename B, typename Cmp = less<iter_value_t<B>>>
multimap<B, A, Cmp> flip_map(const map<A, B> &);

IntelliSense在 typename Cmp 上显示如下错误:

no type named ‘value_type’ in ‘using std::__detail::__iter_traits_impl<long unsigned int, std::indirectly_readable_traits<long unsigned int> >::type = struct std::indirectly_readable_traits<long unsigned int>’ {aka ‘struct std::indirectly_readable_traits<long unsigned int>’}gcc

.cpp 中的以下代码:

template <typename A, typename B>
pair<B, A> flip_pair(const pair<A, B> &p)
{
    return pair<B, A>(p.second, p.first);
}

template <typename A, typename B, typename Cmp>
multimap<B, A, Cmp> flip_map(const map<A, B> &src)
{
    multimap<B, A, Cmp> dst;
    ranges::transform(src, inserter(dst, dst.begin()), flip_pair<A, B>);
    return dst;
}

导致如下构建错误:

MyApp.cpp:2345:57: error: no matching function for call to ‘flip_map(std::map<std::__cxx11::basic_string<char>, long unsigned int>&)’
 2345 |         multimap<size_t, string> myFlippedMap = flip_map(myKeyCount);
      |                                                 ~~~~~~~~^~~~~~~~~~~~
MyApp.cpp:2345:57: note: there is 1 candidate
MyApp.h:147:21: note: candidate 1: ‘template<class A, class B, class Cmp> std::multimap<B, A, Cmp> flip_map(const std::map<K, V>&)’
  147 | multimap<B, A, Cmp> flip_map(const map<A, B> &);
      |                     ^~~~~~~~
MyApp.h:147:21: note: template argument deduction/substitution failed:
MyApp.h:146:35: error: no type named ‘value_type’ in ‘using std::__detail::__iter_traits_impl<long unsigned int, std::indirectly_readable_traits<long unsigned int> >::type = struct std::indirectly_readable_traits<long unsigned int>’ {aka ‘struct std::indirectly_readable_traits<long unsigned int>’}
  146 | template <typename A, typename B, typename Cmp = less<iter_value_t<B>>>
      |                                   ^~~~~~~~

解决方案

B 是map的 ::mapped_type。它与迭代器无关。

template <typename A, typename B, typename Cmp = less<B>>
multimap<B, A, Cmp> flip_map(const map<A, B> &);

注:你可能应该把实现移到头文件中,否则如果其他翻译单元使用该模板,将会产生链接错误。

你还可以通过使用 multimapstd::from_range 构造函数重载来简化函数体,并为 Cmp 增加一个带默认值的参数,以在使用自定义比较器时保持参数推导。

template <typename A, typename B>
pair<B, A> flip_pair(const pair<A, B>& p) {
    return {p.second, p.first};
}

template <typename A, typename B, typename Cmp = std::less<B>>
multimap<B, A, Cmp> flip_map(const map<A, B>& src, Cmp cmp = {}) {
    return {std::from_range, src | std::views::transform(flip_pair<A, B>), cmp};
}

在Compiler Explorer上查看

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章