我有一个需要使用某种地图的类。默认情况下,我想使用std::map
,但我还想让用户能够根据需要使用不同的内容(例如std::unordered_map
或者甚至是用户创建的内容)。
所以我的代码看起来像是
#include <map>
template<class Key, template<class, class> class Map = std::map>
class MyClass {
};
int main() {
MyClass<int> mc;
}
然而,g ++抱怨
test.cpp:3:61: error: template template argument has different template parameters than its corresponding template template parameter
template<class Key, template<class, class> class Map = std::map>
^
test.cpp:8:14: note: while checking a default template argument used here
MyClass<int> mc;
~~~~~~~~~~~^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/map:781:1: note: too many template parameters in template template argument
template <class _Key, class _Tp, class _Compare = less<_Key>,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:3:21: note: previous template template parameter is here
template<class Key, template<class, class> class Map = std::map>
^~~~~~~~~~~~~~~~~~~~~~
1 error generated.
所以看起来g++
不满意std::map
有默认参数。
有没有办法让Map
成为可以接受至少两个模板参数的任何模板?
如果可以,我宁愿坚持使用C ++ 98,但我对C ++ 11持开放态度。
答案 0 :(得分:6)
问题是你的模板模板参数只有两个模板参数,而map
只有四个。
template<class Key, template<class, class, class, class> class Map = std::map>
class MyClass {
};
或者
template<class Key, template<class...> class Map = std::map>
class MyClass {
};
Should compile。
但是,为避免此类问题,请尝试改为使用地图类型,并通过相应的成员typedef提取密钥类型。 E.g。
template <class Map>
class MyClass {
using key_type = typename Map::key_type;
};
答案 1 :(得分:3)
您的代码将在C ++ 17中编译。 C ++ 17及时解决了C ++核心工作组(CWG 150)的一份长期缺陷报告(P0522R0)。
cppreference.com 也讨论了此here,并提供了一个有用的示例:
template<class T> class A { /* ... */ };
template<class T, class U = T> class B { /* ... */ };
template <class ...Types> class C { /* ... */ };
template<template<class> class P> class X { /* ... */ };
X<A> xa; // OK
X<B> xb; // OK in C++17 after CWG 150
// Error earlier: not an exact match
X<C> xc; // OK in C++17 after CWG 150
// Error earlier: not an exact match
使用我的GCC版本(8.3.0)进行测试,我发现使用-std=c++17
标志将成功编译您的程序;使用早期版本的C ++(例如-std=c++14
或-std=c++11
)时将失败。