C++ 模板中运算符[]的重载
我正试图为std::map实例重载操作符[],并对GCC的编译错误感到非常困惑 以下示例将不会编译:C++ 模板中运算符[]的重载,c++,templates,operator-overloading,C++,Templates,Operator Overloading,我正试图为std::map实例重载操作符[],并对GCC的编译错误感到非常困惑 以下示例将不会编译: typedef std::map< int*, int > mymap; namespace std { template <> int & mymap::operator[]( const int* & k) { return begin()->second; }; }; 该示例是否提供合法且可预测的行为?密钥
typedef std::map< int*, int > mymap;
namespace std {
template <>
int & mymap::operator[]( const int* & k) {
return begin()->second;
};
};
该示例是否提供合法且可预测的行为?密钥类型为
int*
为了配合
T& operator[]( const Key& key );
您需要使用:
int & mymap::operator[]( int* const & k) {
不幸的是,在类型之前使用const
是令人困惑的。宣言是否已经通过
T& operator[]( Key const& key );
为您正在尝试的内容提供正确的参数声明会更容易。让我们分析一下您的代码:
int& mymap::operator[](const int* &k)
{
return begin ()->second;
};
这是错误的,因为该参数是对指向常量int的指针的引用,而不是对指向int的常量指针的引用
const
的位置让您感到困惑,请将其改写为:
int& mymap::operator[](int *const &k)
{
return begin ()->second;
};
从17.6.4.2.1/2开始:
< > C++程序的行为如果声明则是未定义的
-一个
标准库的任何成员函数的显式专门化
类模板,或
因此,现在所有的赌注都没有了,编译器没有义务编译您的代码(其他答案显示了为什么编译器似乎接受使用typedef的代码,但这仍然不能使其合法化)
在17.4.3.1/1中,C++98稍微不太明确:
< >对于C++程序添加声明或定义是未定义的
除非另有说明,否则将命名空间std或命名空间std中的命名空间
明确规定。程序可以为任何标准添加模板专门化
名称空间标准的库模板。此类专门化(完整或
标准库模板的部分)会导致未定义的行为
除非声明依赖于用户定义的外部名称
链接,除非专业化符合标准库
对原始模板的要求
现在,还不清楚这是否严格禁止对
std
命名空间模板的成员进行专门化(相对于容器模板本身的完全或部分专门化),但您的特定代码肯定是未定义的,因为它不专门化用户定义的外部链接名称。,这可能是未定义的行为。使用指针作为映射的键时也要小心,它将被用作键,而不是它所指向的。为了所有正确和公正的爱,不要做这种坏事。@RichardHodges,您是否会为需要专门化的std容器实例创建一个类包装器?@Marat如果您认为需要专门化标准容器的操作符,那么肯定有更好的方法来表达您的意图。我有兴趣看到一个完整的(简短的)计划,使用这个专业。我很乐意只使用标准的习惯用法来重构它。这个答案比@RSahu已经提供的答案有什么帮助?这个答案如何与下面的参考一起工作?你的消息来源是什么?“仅当声明依赖于用户定义的类型且专门化满足原始模板的所有要求时,才允许将任何标准库模板的模板专门化添加到命名空间std中,除非禁止此类专门化。”()我的来源是C++11标准草案N3337(与最终版本非常接近)。您的引用似乎只引用命名空间中的模板,而不是此类模板的成员函数。那么,它是否适用于C++98?我似乎找不到任何限制的地方。
int& mymap::operator[](int *const &k)
{
return begin ()->second;
};