Mar*_*rat -1 c++ templates operator-overloading
我正在尝试为一个std :: map实例重载operator [],并对GCC的编译错误感到非常困惑.
以下示例将无法编译:
typedef std::map< int*, int > mymap;
namespace std {
template <>
int & mymap::operator[]( const int* & k) {
return begin()->second;
};
};
Run Code Online (Sandbox Code Playgroud)
这个失败了:
错误:对于'int&std :: map,std :: allocator >> :::运算符[](const int*&)'的模板ID'运算符[] <>'与任何模板声明都不匹配
但如果你int*用myintp(typedef int* myintp)替换它会编译得很好.
有趣的是,为什么这里需要模板<>和命名空间.
更新: 我简化了示例.
只有当声明取决于用户定义的类型且专业化满足原始模板的所有要求时,才允许将任何标准库模板的模板特化添加到命名空间std,除非禁止此类特殊化.
typedef std::map< myclass*, int > mymap;
namespace std {
template <>
int & mymap::operator[]( myclass* const & k) {
return begin()->second;
};
};
Run Code Online (Sandbox Code Playgroud)
这个例子会提供合法且可预测的行为吗?
从17.6.4.2.1/2:
如果声明,C++程序的行为是不确定的
- 标准库类模板的任何成员函数的显式特化,或
所以所有的赌注都关闭了,编译器没有义务编译你的代码(其他答案显示了为什么编译器似乎接受使用typedef的代码,但这仍然不合法).
在17.4.3.1/1中,C++ 98略显不明确:
除非另有说明,否则C++程序未定义向命名空间std中的命名空间std或命名空间添加声明或定义.程序可以将任何标准库模板的模板特化添加到命名空间std.标准库模板的这种特化(完整或部分)会导致未定义的行为,除非声明取决于用户定义的外部链接名称,除非特化符合原始模板的标准库要求.
现在,它有点不清楚,如果这种严格禁止专门的模板的成员std命名空间(VS容器模板本身的全部或部分专门化),但您的特定代码肯定是不确定的,因为它没有专注于一个用户定义的名称外部联系.