首页 文章

在模板中重载operator []

提问于
浏览
-1

我正在尝试为一个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 *&)''与任何模板声明都不匹配

但是如果用 myintptypedef int* myintp )替换 int* ,它将编译得很好 .

有趣的是,为什么这里需要模板<>和命名空间 .

Update: 我简化了示例 .

只有当声明取决于用户定义的类型且专业化满足原始模板的所有要求时,才允许将任何标准库模板的模板特化添加到命名空间std,除非禁止此类特殊化 .

typedef std::map< myclass*, int >           mymap; 
namespace std {
template <>
int & mymap::operator[]( myclass* const & k) {
    return begin()->second;
};
};

这个例子会提供合法且可预测的行为吗?

3 回答

  • 6

    密钥类型是 int* .

    为了匹配

    T& operator[]( const Key& key );
    

    你需要使用:

    int & mymap::operator[]( int* const & k) {
    

    不幸的是,在类型之前使用 const 令人困惑 . 如果声明已经

    T& operator[]( Key const& key );
    

    对于你正在尝试的东西,想出正确的论证声明会更容易 .

  • 2

    从17.6.4.2.1 / 2:

    如果C语言声明 - 标准库类模板的任何成员函数的显式特化,或者C程序的行为是未定义的,或者

    所以所有的赌注都关闭了,编译器没有义务编译你的代码(其他答案显示了为什么编译器似乎接受使用typedef的代码,但这仍然不合法) .

    在第17.4.3.1/1节中,C 98略显不明确:

    除非另有说明,否则C程序未定义向命名空间std中的命名空间std或命名空间添加声明或定义 . 程序可以将任何标准库模板的模板特化添加到命名空间std . 标准库模板的这种特化(完整或部分)会导致未定义的行为,除非声明取决于用户定义的外部链接名称,除非特化符合原始模板的标准库要求 .

    现在,有点不清楚这是否严格禁止专门化 std 命名空间模板的成员(相对于容器模板本身的完全或部分特化),但是您的特定代码肯定是未定义的,因为它不专注于用户定义的名称外部联系 .

  • 0

    让我们分析你的代码:

    int& mymap::operator[](const int* &k)
    {
        return begin ()->second;
    };
    

    这是错误的,因为参数是对指向const int的指针的引用,而不是对指向int的const指针的引用 .

    const 的位置让你很困惑,所以把它重写为:

    int& mymap::operator[](int *const &k)
    {
        return begin ()->second;
    };
    

相关问题