std:map作为模板参数的模板推导失败 [英] Template deduction fails for std:map as template parameter

查看:361
本文介绍了std:map作为模板参数的模板推导失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在C ++ 11中实现一个简单的LRU缓存。我几乎涵盖了所有内容,但是只有一个小问题。假设我有以下模板类定义:

I'm implementing a simple LRU cache in C++11. I pretty much have it covered but there's just one minor problem. 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

在KeyToValue类型下,MSVC2013出现以下编译错误:错误1错误C2976: std :: map:模板参数过少c:\x\visual studio 2013\项目\缓存\lru_stl\lru_stl.h 17 1 LRU_STL

At 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

第17行是:

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

似乎模板推导失败。这可能是一个非常简单的问题,但我仍然找不到。为了完整起见,下面是一个示例:

Seems like the template deduction fails. It may be a very simple problem but I just couldn't find it yet. For completeness here's 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");

已提供错误。做过修复。仍然发生相同的错误:std :: map模板参数太少。

The error is already provided. Done mentioned fixes. Still the same error occurs: std::map too few template arguments.

为了完整性,如果我删除所有内容并创建一个TEST类:

Just for completeness if I remove 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 the class results in the exact same error message.

@Update:
在这种特定情况下,VC ++编译器似乎无法处理默认模板参数。为了解决这个问题,我必须将所有四个模板参数添加到typedef中,这样定义就变得像这样:

@Update: VC++ Compiler seems to be unable to process default template parameters in this particular scenario. To solve the issue I had to add all four template parameters to the typedef and so the definition became like:

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

这就是这个问题的全部。感谢所有尝试提供帮助的人以及这位专业的绅士:我对这个问题甚至都不了解,让我们DOWNVOTE it !!!。你真的很棒!祝你最好的人。...

That would be all to this issue. Thanks for all who tried to help and for that professional gentleman with: 'I don't have even the slightest idea about this question, Let's DOWNVOTE it!!!'. You really are amazing! Wish you the best man....

推荐答案

您错过了两分。

首先, 模板模板参数 应该是这样的:

First, template template parameter should be like this:

template<参数列表>类名

所以您的

template<typename...> Map

应该是

template<typename...> class Map

第二,应该使用类型名称依赖名称在您的代码中, std :: list< Key> :: iterator 是一个从属名称(取决于 Key )。因此,应改用 typename std :: list< Key> :: iterator

Second, 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 instead.

这是我正确的测试代码。

Here's my corrected 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;
}

它在g ++ 4.9.1和clang ++ 3.5中均有效。

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

这似乎是由于VC ++的愚蠢。如果将 full 模板参数提供给 std :: map (包括比较器和分配器),则可能会起作用,因为VC ++似乎无法处理在这种情况下为默认模板参数。

It seems to be due to VC++'s foolishness. It may work if you give the full template parameter to std::map, including comparer and allocator, since VC++ seems not to be able to process default template parameter in this case.

这篇关于std:map作为模板参数的模板推导失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆