如何避免 cast operator() 和 access operator[] 冲突?
How do I avoid cast operator() and access operator[] conflict?
我确定之前有人问过,但我找不到。
我有一个class封装std::string
。在内部,我想将类型转换重载到 char*
和访问 operator[]
.
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 overloads have similar conversions
编译器无法决定要做什么:
- 直接使用重载
operator[]
- 首先转换为
char*
,使用 operator()
,最后 operator[]
覆盖生成的 char*
数组
有什么方法可以保留这两个操作员吗?对于许多功能,char*
和 const char*
对使用 String
的 operator() 非常有帮助,但在所有其他情况下直接使用 operator[](不尝试首先转换为 char*
)。
我想这个问题的答案可能是否。这就是为什么在 std::string
中没有 char*
转换运算符的原因,但也许在最近的 C++ 标准中发生了一些变化?
编辑: 我可以用 GCC 编译上面的代码,但它在 VS (x86) 中失败了。
Error C2666 'String::operator []': 4 overloads have similar conversions
始终在启用警告的情况下编译代码,对于 gcc
和 clang
,命令行选项是 -Wall -Wextra -Werror
。警告会告诉您 operator[]
需要 return 一个值。
在 32 位模式下的表达式 s[0]
中 clang
和 msvc
编译器考虑 int
索引的 标准转换 unsigned
(32 位 size_t
)与 String
到 char*
的 用户定义转换 具有相同等级。请参阅编译器错误消息 here。后一种转换是 用户定义的转换 的排名比任何 标准转换 都要差,但编译器无法解决这种关系。我不确定这里适用哪个标准规则。
解决方法是添加另一个 operator[]
的重载,它接受签名的 ptrdiff_t
索引:
char operator[](ptrdiff_t pos) const { return m_str[pos]; }
char& operator[](ptrdiff_t pos) { return m_str[pos]; }
我确定之前有人问过,但我找不到。
我有一个class封装std::string
。在内部,我想将类型转换重载到 char*
和访问 operator[]
.
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 overloads have similar conversions
编译器无法决定要做什么:
- 直接使用重载
operator[]
- 首先转换为
char*
,使用operator()
,最后operator[]
覆盖生成的char*
数组
有什么方法可以保留这两个操作员吗?对于许多功能,char*
和 const char*
对使用 String
的 operator() 非常有帮助,但在所有其他情况下直接使用 operator[](不尝试首先转换为 char*
)。
我想这个问题的答案可能是否。这就是为什么在 std::string
中没有 char*
转换运算符的原因,但也许在最近的 C++ 标准中发生了一些变化?
编辑: 我可以用 GCC 编译上面的代码,但它在 VS (x86) 中失败了。
Error C2666 'String::operator []': 4 overloads have similar conversions
始终在启用警告的情况下编译代码,对于 gcc
和 clang
,命令行选项是 -Wall -Wextra -Werror
。警告会告诉您 operator[]
需要 return 一个值。
在 32 位模式下的表达式 s[0]
中 clang
和 msvc
编译器考虑 int
索引的 标准转换 unsigned
(32 位 size_t
)与 String
到 char*
的 用户定义转换 具有相同等级。请参阅编译器错误消息 here。后一种转换是 用户定义的转换 的排名比任何 标准转换 都要差,但编译器无法解决这种关系。我不确定这里适用哪个标准规则。
解决方法是添加另一个 operator[]
的重载,它接受签名的 ptrdiff_t
索引:
char operator[](ptrdiff_t pos) const { return m_str[pos]; }
char& operator[](ptrdiff_t pos) { return m_str[pos]; }