Template output is not performed for std: map as a template parameter

I use the simple LRU cache in C ++ 11. I pretty much covered it, but there is only one minor issue. Let's say I have the following template class definition:

#ifndef _LRU_STL_H_ #define _LRU_STL_H_ #include <functional> #include <cassert> #include <list> template <typename KeyType, typename ValueType, template<typename...> class Map> class LRU { public: typedef Map<KeyType, std::pair<ValueType, typename std::list<KeyType>::iterator>> KeyToValueType; LRU(const std::function<ValueType(const KeyType&)> &Function, size_t Capacity) : _Function(Function), _Capacity(Capacity) { assert(_Capacity != 0); } ... private: ... std::function<ValueType(const KeyType&)> _Function; const size_t _Capacity; KeyToValueType _KeyToValue; }; #endif 

In the KeyToValue type, I get the following compilation error with MSVC2013: Error 1 error C2976: 'std :: map': too few template arguments c: \ x \ visual studio 2013 \ projects \ caching \ lru_stl \ lru_stl.h 17 1 LRU_STL

17th line:

 typedef Map<KeyType, std::pair<ValueType, typename std::list<KeyType>::iterator>> KeyToValueType; 

It seems that the deduction of the pattern failed. This may be a very simple problem, but I just could not find it. For completeness, here is an example:

 std::function<std::string(std::string)> functionToCache = [](std::string & str) { std::string reverse; reverse.reserve(str.size()); std::copy(str.begin(), str.end(), reverse); return reverse; }; LRU<std::string, std::string, std::map> LRU(functionToCache, 5); std::string Hello_World = LRU("Hello World"); assert(Hello_World == "dlroW olleH"); 

Error already provided. The mentioned corrections are made. The same error still occurs: std :: map has too few template arguments.

Just for completeness, if I delete everything and create a TEST class:

 template <typename A, typename B, template <typename ...> class Map> class TEST { typename Map<A, std::pair<B, typename std::list<A>::iterator>> CMAP; public: TEST(void) { } }; 

Trying to instantiate a class in the same error message.

@Update: The VC ++ compiler does not seem to be able to handle the default template options in this particular scenario. To solve the problem, I had to add all four template parameters to typedef, and so the definition was as follows:

 template <typename K, typename V, template <typename...> class Map> class Test { typedef Map<K, std::pair<V, typename std::list<K>::iterator>, std::less<K>, std::allocator<std::pair<const K, typename std::list<K>::iterator>>> MapType; }; 

That's all. Thanks to everyone who tried to help for this professional gentleman: "I don’t even have the slightest idea about this issue, let DOWNVOTE it !!!". You are really amazing! I wish you a better person ....

0
source share
1 answer

Your missing two points.

First, the template template parameter should look something like this:

template < parameter-list > class name

So your

 template<typename...> Map 

it should be

 template<typename...> class Map 

Secondly, you should use typename with dependent names. In your code, std::list<Key>::iterator is a dependent name (depending on Key ). So you should use typename std::list<Key>::iterator .


Here is my adjusted test code.

 #include <list> #include <map> template <typename Key, typename Value, template <typename...> class Map> class Test { public: typedef Map< Key, std::pair<Value, typename std::list<Key>::iterator> > KeyToValueType; }; int main() { Test<int, char, std::map>::KeyToValueType asdf; } 

It worked in both g ++ 4.9.1 and clang ++ 3.5.


This seems to be due to the stupidity of VC ++. It may work if you give the full template parameter std::map , including the comparator and the allocator, since VC ++ does not seem to be able to handle the default template parameter in this case.

+1
source

Source: https://habr.com/ru/post/975890/


All Articles