传递std::map作为模板模板参数时出错

Error when pass std::map as template template argument

本文关键字:出错 参数 std map 传递      更新时间:2023-10-16

我定义了一个这样的函数,其中有一个模板模板类

template<typename Key, typename Value, template <typename, typename> class Map>
    struct ForEachOf {
        void operator()(const Map<Key, Value>& map, std::function<void (Key, Value)> func) {
            for(const auto& pair : map) {
                func(pair.first, pair.second);
            }
        }
    };
std::map<int, string> m { {1, "foo"}, {3, "bar"}};
ForEachOf<int, string, std::map> forEachOf;
    forEachOf(m, [](int key, string value) {
        cout << key << value;
    });

但是,上面的代码无法编译。错误如下:

error: template template argument has different template parameters
      than its corresponding template template parameter
    ForEachOf<int, string, std::map> forEachOf;
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__tree:1119:5: note: too many template
      parameters in template template argument
    template <class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY map;
note: previous template template parameter is here
    template<typename Key, typename Value, template <typename, typename> class Map>

然后这里如何传递std::map作为模板模板参数?

你的问题是::std::map没有只接受两个模板参数。

解决方案是简单地添加一个模板,它只接受两个参数,而不是四个:

template<typename key, typename value>
using mymap = std::map<key, value>;

(见)

或者,将缺失的参数添加到它们的默认值中:

template<typename Key, typename Value, template <typename, typename, typename, typename> class Map>
struct ForEachOf {
    void operator()(const Map<Key, Value, ::std::less<Key>, ::std::allocator<std::pair<const Key, T> >>& map, std::function<void (Key, Value)> func) {
        for(const auto& pair : map) {
            func(pair.first, pair.second);
        }
    }
};

(见)

可以类似地使用可变类型模板来编写:

template<typename Key, typename Value, template <typename...> class Map>
struct ForEachOf {
     void operator()(const Map<Key, Value>& map, std::function<void (Key, Value)> func) {
        for(const auto& pair : map) {
            func(pair.first, pair.second);
        }
    }
};

(见)

当然,你也可以创建一个模板函数来获取映射并推导出所有内容:

#include <map>
#include <string>
#include <iostream>
template<typename T, typename F>
void ForEachOf(T&& map, F&& func) {
    for(auto& pair : map) {
        func(pair.first, pair.second);
    }
}
int main(void) {
    std::map<int, std::string> m { {1, "foo"}, {3, "bar"}};
    ForEachOf(m, [](auto key, auto value) {
        ::std::cout << key << value;
    });
}

(见)

一开始并不需要模板参数。可以改成

template<typename Map>
struct ForEachOf {
  void operator()(const Map& map,
      std::function<void (typename Map::key_type, typename Map::mapped_type)> func) const {
            for(const auto& pair : map) {
                func(pair.first, pair.second);
            }
        }
    };

或者

template <typename F>
void operator() (const Map& map, F func) const { ... }