C++ C++;带有默认参数的模板参数

C++ C++;带有默认参数的模板参数,c++,templates,C++,Templates,我有一个类需要使用某种映射。默认情况下,我希望使用std::map,但我也希望用户能够根据自己的需要使用不同的东西(例如std::unordered_map,甚至可能是用户创建的) 所以我有这样的代码 #include <map> template<class Key, template<class, class> class Map = std::map> class MyClass { }; int main() { MyClass<int&

我有一个类需要使用某种映射。默认情况下,我希望使用
std::map
,但我也希望用户能够根据自己的需要使用不同的东西(例如
std::unordered_map
,甚至可能是用户创建的)

所以我有这样的代码

#include <map>

template<class Key, template<class, class> class Map = std::map>
class MyClass {
};

int main() {
  MyClass<int> mc;
}
#包括
模板
类MyClass{
};
int main(){
MyClass 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.
test.cpp:3:61:错误:模板参数的模板参数与其对应的模板参数不同
模板
^
test.cpp:8:14:注意:在检查此处使用的默认模板参数时
MyClass mc;
~~~~~~~~~~~^
/Library/Developer/CommandLineTools/usr/bin/./include/c++/v1/map:781:1:注意:模板参数中的模板参数太多

template问题在于,您的template参数只有两个模板参数,而
map
有四个模板参数

template<class Key, template<class, class, class, class> class Map = std::map>
class MyClass {
};
模板
类MyClass{
};

模板
类MyClass{
};
.
但是,为了避免此类问题,请尝试使用映射类型,并通过相应的成员typedef提取密钥类型。例如

template <class Map>
class MyClass {
    using key_type = typename Map::key_type;
};
模板
类MyClass{
使用key\u type=typename映射::key\u type;
};

您的代码将在C++17中编译。C++核心工作组()的一个长期缺陷报告及时地解决(C++)17。 cppreference.com还将讨论这一点,并提供一个有用的示例:

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
模板类A{/*…*/};
模板类B{/*…*/};
模板类C{/*…*/};
模板类X{/*…*/};
X xa;//好啊
X xb;//C++17中CWG150之后的OK
//早期错误:不完全匹配
X xc;//C++17中CWG150之后的OK
//早期错误:不完全匹配

使用我的GCC版本(8.3.0)进行测试,我发现使用
-std=c++17
标志将成功编译您的程序;在使用C++的早期版本(例如,<代码> -STD= C++ 14 或 -STD= C++ 11 )时,将失败。

如果你对C++ 11开放,你可以说“代码>模板类映射= STD::MAP< /代码>,但真正的解决方案是对类型进行参数化,而不是在模板上。”KerrekSB最初是这样做的,但我需要地图和地图。我也有这些的默认模板参数,但我认为如果用户只指定Map会很方便,如果他们没有指定Map或Map,这些参数将自动确定。有没有更好的方法避免模板参数?可能的重复。谢谢!g++很高兴。但是,这禁止选择接受模板参数或除类型以外的任何参数的
Map
类型,对吗?出于好奇,有没有办法允许
映射
的可选参数为任意值?@0x499602D2这正是我在文章最后一句中提出的建议。@math4tots不,这是不可能的。(在某个地方也有一篇关于这个问题的流行的未回答的SO帖子…)这就是为什么你应该选择地图类型而不选择模板。它非常灵活。@0x499602D2源代码?在post Urbana邮件中看不到任何内容。@0x499602D2这些内容与获取任意类型的模板参数无关。
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