将 std::map 作为模板模板参数传递时出错
Error when pass std::map as template template argument
我定义了一个这样的函数,里面有一个template模板class
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
作为template模板参数传进去呢?
你一开始并不真的需要模板模板参数。你可以做到
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 { ... }
你的问题是 ::std::map
does not take only two template parameters.
解决方案就是添加一个只接受两个参数而不是四个参数的模板:
template<typename key, typename value>
using mymap = std::map<key, value>;
(See it)
或者,或者添加缺少的参数及其默认值:
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);
}
}
};
(See it)
同样可以使用可变类型模板编写:
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);
}
}
};
(See it)
当然,您也可以只创建一个模板函数来获取地图并推导所有内容:
#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;
});
}
(See it)
我定义了一个这样的函数,里面有一个template模板class
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
作为template模板参数传进去呢?
你一开始并不真的需要模板模板参数。你可以做到
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 { ... }
你的问题是 ::std::map
does not take only two template parameters.
解决方案就是添加一个只接受两个参数而不是四个参数的模板:
template<typename key, typename value>
using mymap = std::map<key, value>;
(See it)
或者,或者添加缺少的参数及其默认值:
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);
}
}
};
(See it)
同样可以使用可变类型模板编写:
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);
}
}
};
(See it)
当然,您也可以只创建一个模板函数来获取地图并推导所有内容:
#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;
});
}
(See it)