避免强制转换运算符()和访问运算符[]冲突[保持中]

问题描述 投票:0回答:1

我确定应该先询问它,但找不到。

我有一个封装std :: string的类,我想在其中将类型转换重载到char *和访问运算符[]。

class String
{
public :
    String(const char* s) { m_str = s; }
    const char* str() const  { return m_str.c_str(); }
    char* str()  {  return &m_str[0]; }
    char operator[](size_t pos) const { return m_str[pos]; }
    char& operator[](size_t pos) { return m_str[pos]; }
    operator const char*() const { return str(); }  // cast operator
    operator char*() { return str(); }  // cast operator
protected:
    std::string m_str;
};

void main()
{
    String s = "1234";
    if(s[0] != '1')   //'String::operator []': 4 overloads have similar conversions !!!!!
        std::cout << "Error" << endl;
}

当然,现在的问题是,当我尝试使用String []时,收到错误消息“ 4重载具有相似的转换”,编译器无法决定要执行以下操作:1)直接使用重载运算符[]2)首先使用operator()转换为char *,然后通过char *数组转换为operator []

是否有办法保留这两个运算符?对于许多函数,等等。接受char *和const char *以使用String的operstor(),但在所有其他情况下,直接使用operator [](不尝试转换为char *)。

我想对此的回答可能是“否”,这就是为什么在[[std :: string中没有char *强制转换运算符,但是在最新的C ++标准中可能有所改变。

编辑:我可以使用GCC编译上述内容,但对于VS(x86)则无法进行。错误C2666'String :: operator []':4个重载具有相似的转换
c++ casting operator-overloading stdstring typecasting-operator
1个回答
0
投票
始终在启用警告的情况下编译代码,对于gccclang,命令行选项为-Wall -Wextra -Werror。警告将告诉您operator[]需要返回一个值。

修复:

char operator[](size_t pos) const { return m_str[pos]; } char& operator[](size_t pos) { return m_str[pos]; }

使您的代码成功编译。

我可以使用GCC编译上面的代码,但是在VS上失败。

使用上述修补程序VS compiles it successfully


在解析表达式s[0]中,将考虑该类的以下运算符:

char operator[](size_t pos) const; char& operator[](size_t pos); operator const char*() const; operator char*();

[char& operator[](size_t pos)要求将类型为0的索引int转换为size_t

operator char*后接内置operator(char*, int),需要从thischar*

用户定义的转换。

A

用户定义的转换

被认为比任何标准转换都要糟糕。在64位平台上,size_tunsigned longintunsigned long是整数

promotion

,因为unsigned long具有比int高的rank在32位平台上,size_tunsignedintunsigned是整数

转换

,因为unsignedint具有相同的rank标准说,第二个int自变量的

promotion

优于user-defined conversion_ of the 1st argument this`。但是根据标准,第二个参数的conversion与第一个参数的用户定义的转换被认为是模棱两可的,并且调用失败。解决错误的一种方法是使用带符号的ptrdiff_t而不是无符号的size_t作为索引:

char operator[](ptrdiff_t pos) const { return m_str[pos]; } char& operator[](ptrdiff_t pos) { return m_str[pos]; }

这在unsigned索引because上也很好用:

如果目标类型是带符号的,则如果源整数可以用目标类型表示,则该值不会更改。否则结果是实现定义的(直到C ++ 20)。

换言之,当值不变时,unsignedint不被视为转换。

© www.soinside.com 2019 - 2024. All rights reserved.