我确定应该先询问它,但找不到。
我有一个封装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个重载具有相似的转换gcc
和clang
,命令行选项为-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)
,需要从this
到char*
的
用户定义的转换。
A 用户定义的转换
被认为比任何标准转换都要糟糕。在64位平台上,size_t
为unsigned long
,int
至unsigned long
是整数promotion
,因为unsigned long
具有比int
高的rank。在32位平台上,size_t
为unsigned
,int
至unsigned
是整数转换
,因为unsigned
与int
具有相同的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)。
换言之,当值不变时,unsigned
至int
不被视为转换。