2

I defined a function like this, in which there is a template 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; }); 

However, above code is not able to compile. the error is like:

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> 

Then How to pass std::map as the template template parameter here?

2
  • 4
    std::map has four template parameters, not two. Commented Aug 29, 2015 at 18:59
  • You can use one regular template parameter T, and make func accept typename T::key_type and typename T::mapped_type Commented Aug 29, 2015 at 19:03

2 Answers 2

7

Your problem is that ::std::map does not take only two template parameters.

The solution is simply to add a template that takes only two parameters instead of four:

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

(See it)

Or, alternatively add the missing arguments with their defaults:

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)

Which can similarly be written by using a variadic type template:

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)

Of course, you could also just create a template function that takes the map and deduces everything:

#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)

Sign up to request clarification or add additional context in comments.

2 Comments

Really, using template<class...>class Map seems easier than writing mymap
@Yakk Totally forgot that option :)
7

You don't really need template template parameter in the first place. You could make it

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); } } }; 

or even

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.