我正在尝试为一个std :: map实例重载operator [],并对GCC的编译错误感到非常困惑 .
以下示例将无法编译:
typedef std::map< int*, int > mymap;
namespace std {
template <>
int & mymap::operator[]( const int* & k) {
return begin()->second;
};
};
这个失败了:
error:template-id'operator [] <>'for'int&std :: map,std :: allocator >> :: :: [(const int *&)''与任何模板声明都不匹配
但是如果用 myintp
( typedef int* myintp
)替换 int*
,它将编译得很好 .
有趣的是,为什么这里需要模板<>和命名空间 .
Update: 我简化了示例 .
只有当声明取决于用户定义的类型且专业化满足原始模板的所有要求时,才允许将任何标准库模板的模板特化添加到命名空间std,除非禁止此类特殊化 .
typedef std::map< myclass*, int > mymap;
namespace std {
template <>
int & mymap::operator[]( myclass* const & k) {
return begin()->second;
};
};
这个例子会提供合法且可预测的行为吗?
3 回答
密钥类型是
int*
.为了匹配
你需要使用:
不幸的是,在类型之前使用
const
令人困惑 . 如果声明已经对于你正在尝试的东西,想出正确的论证声明会更容易 .
从17.6.4.2.1 / 2:
所以所有的赌注都关闭了,编译器没有义务编译你的代码(其他答案显示了为什么编译器似乎接受使用typedef的代码,但这仍然不合法) .
在第17.4.3.1/1节中,C 98略显不明确:
现在,有点不清楚这是否严格禁止专门化
std
命名空间模板的成员(相对于容器模板本身的完全或部分特化),但是您的特定代码肯定是未定义的,因为它不专注于用户定义的名称外部联系 .让我们分析你的代码:
这是错误的,因为参数是对指向const int的指针的引用,而不是对指向int的const指针的引用 .
const
的位置让你很困惑,所以把它重写为: