C++ 将自定义类型的转换运算符重载为 std::string
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3518145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ overloading conversion operator for custom type to std::string
提问by Markus
I hope someone might be able to answer why the following doesn't work. Bear with me though, I am still very much a noob... I just cannot get to the bottom of why the following
我希望有人能够回答为什么以下不起作用。不过请容忍我,我仍然是一个菜鸟......我无法弄清楚为什么以下
using namespace std;
#include <string>
#include <iostream>
class testClass
{
public:
operator char* () {return (char*)"hi";};
operator int () {return 77;};
operator std::string () {return "hello";};
};
int main()
{
char* c;
int i;
std::string s = "goodday";
testClass t;
c = t;
i = t;
s = t;
cout<< "char: " << c << " int: " << i << " string: "<<s<<endl;
return 0;
}
gives me a compile time error:
给我一个编译时错误:
myMain.cpp: In function ‘int main()':
myMain.cpp:23: error: ambiguous overload for ‘operator=' in ‘s = t'
/usr/include/c++/4.2.1/bits/basic_string.h:500: note: candidates are: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:508: note: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:519: note: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
If I do not attempt the assignment
如果我不尝试分配
s = t;
it does work.
它确实有效。
I've been trying for hours to even comprehend the error message, but what's puzzling me most is that is does work for char*.
我已经尝试了几个小时来理解错误消息,但最让我困惑的是它确实适用于 char*。
I'm grateful for any hint. Thanks! Markus
我很感激任何提示。谢谢!马库斯
回答by Tony Delroy
What the error is trying to explain is that your assignment "s = t
", where s
is a std::string
, would be valid if t
were a std::string
too, or if t
were a [const
] char*
. Your conversion operators can convert a t
into either, so the compiler has no basis on which to choose one over the other....
错误试图解释的是,如果是 a或如果是 [ ] ,则您的赋值“ s = t
”(其中s
是 a std::string
)也是有效的。您的转换运算符可以将 a 转换为其中之一,因此编译器没有依据来选择其中一个....t
std::string
t
const
char*
t
You can disambiguate this explicitly by selecting the conversion you want:
您可以通过选择所需的转换来明确消除歧义:
s = t.operator std::string();
s = static_cast<std::string>(t);
Or you can provide only one of the conversions and let the user do a further conversion when necessary.
或者,您可以仅提供一种转换,并在必要时让用户进行进一步的转换。
You may find though - in the end - that any conversion operator is more trouble than it's worth... it's telling that std::string
itself doesn't provide a conversion operator to const char*
.
您可能会发现 - 最后 - 任何转换运算符都比它的价值更麻烦......这表明std::string
它本身不提供转换运算符到const char*
.
回答by Chubsdad
$13.3.1.5/2 states- "The conversion functions of S and its base classes are considered. Those that are not hidden within S and yield type T or a type that can be converted to type T via a standard conversion sequence (13.3.3.1.1) are candidate functions. Conversion functions that return a cv-qualified type are considered to yield the cv-unqualified version of that type for this process of selecting candidate functions. Conversion functions that return “reference to cv2 X” return lvalues of type “cv2 X” and are therefore considered to yield X for this process of selecting candidate functions."
$13.3.1.5/2 声明-“考虑了 S 及其基类的转换函数。那些没有隐藏在 S 中并产生类型 T 或可以通过标准转换序列转换为类型 T 的类型(13.3.3.1 .1) 是候选函数。返回一个 cv 限定类型的转换函数被认为会为这个选择候选函数的过程产生该类型的 cv 非限定版本。返回“对 cv2 X 的引用”的转换函数返回类型的左值“cv2 X”,因此被认为在选择候选函数的过程中产生 X。”
The assignment s = t works as follows:
赋值 s = t 的工作原理如下:
a) All members in the type of 't' (testClass) are considered which can convert 't' to 's'.
a) 考虑可以将 't' 转换为 's' 的 't' 类型(testClass)中的所有成员。
Candidate 1: operator string(); // s created using member string::operator=(string const&)
Candidate 2: operator char *() // s created using member string::operator=(char const*)
Candidate 3: operator char *() // s created using member string::operator=(char *)
b) All of the above candidates are viable (that is, in absence of other candidates, the compiler can successfully resolve the function call to either of them)
b) 以上所有候选都是可行的(即在没有其他候选的情况下,编译器可以成功解析对其中任何一个的函数调用)
c) However, now the best viable candidate has to be determined. The Conversion sequences involved are:
c) 但是,现在必须确定最佳可行的候选者。涉及的转换序列是:
Candidate 1: U1 : operator string()
Candidate 2: U2 : operator char*()->const qualification to match string::operator=(char const*)
Candidate 3: U3 : operator char*()
$13.3.3.1.1/3 states - "The rank of a conversion sequence is determined by considering the rank of each conversion in the sequence and the rank of any reference binding (13.3.3.1.4). If any of those has Conversion rank, the sequence has Conversion rank;"
$13.3.3.1.1/3 声明-“转换序列的等级是通过考虑序列中每个转换的等级和任何参考绑定的等级(13.3.3.1.4)来确定的。如果其中任何一个具有转换等级,该序列具有转换等级;"
This means that U1, U2 and U3 are all having Conversion rank and at a first level neither s better than the other. However, the standard also states
这意味着 U1、U2 和 U3 都具有转换等级,并且在第一级别上都不比另一个更好。但是,该标准还指出
User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function or constructor and if the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2.
如果用户定义的转换序列 U1 包含相同的用户定义的转换函数或构造函数,并且如果 U1 的第二个标准转换序列优于 U2 的第二个标准转换序列,则用户定义的转换序列 U1 是比另一个用户定义的转换序列 U2 更好的转换序列.
So, let's see what this means.
那么,让我们看看这意味着什么。
Between U1 and U2, they involve, different conversion functions and hence none is better than the other
在 U1 和 U2 之间,它们涉及不同的转换函数,因此没有一个比另一个更好
Between U1 and U3, they involve, different conversion functions and hence none is better than the other
在 U1 和 U3 之间,它们涉及不同的转换函数,因此没有一个比另一个更好
So what about U1 and U2. They involve the same conversion function, which satisfies the first part of the "and" condition above
那么U1和U2呢?它们涉及相同的转换函数,满足上面“与”条件的第一部分
So what about the part "and if the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2."
那么“如果U1的第二个标准转换序列比U2的第二个标准转换序列更好”那部分呢?
In U2, the second standard conversion sequence requires a const qualification, where in U3 this is not required. The second standard conversion sequence of U3 is an Exact Match.
在 U2 中,第二个标准转换序列需要 const 限定,而在 U3 中则不需要。U3 的第二个标准转换序列是精确匹配。
But as Table 9 in the Standard states, CV qualification is also considered to be an Exact Match.
但正如标准中的表 9 所述,简历资格也被视为完全匹配。
Therefore U2 and U3 are also really indistinguisable as far as overload resolution is considered.
因此,就过载分辨率而言,U2 和 U3 也确实无法区分。
This means U1, U2 and U3 are all really as good as each other and the compiler finds resolving the call(as part of assignment statement) as ambiguous, as there is no unambiguous bestviable function
这意味着 U1、U2 和 U3 真的彼此一样好,编译器发现解析调用(作为赋值语句的一部分)是不明确的,因为没有明确的最佳可行函数
回答by tc.
There's no exact std::string::operator=. The candidates are, paraphrased,
没有确切的 std::string::operator=。候选人是,解释,
s = (const std::string)(std::string)t;
s = (const char*)t;
s = (char)(int)t;
I think things will work if you change it to return const std::string.(EDIT:I'm wrong.) Also note that the first function should return const char *. If you need to cast a string literal to char*, you're doing something wrong; string literals are notwriteable.
我认为如果您将其更改为返回 const std::string,事情就会奏效。(编辑:我错了。)还要注意第一个函数应该返回 const char *。如果您需要将字符串文字转换为 char*,那么您就做错了;字符串文字是不可写的。
回答by Steven Sudit
Actually, it's because std::string
offers an assignment operator that takes a const char*
.
实际上,这是因为std::string
提供了一个赋值运算符,它采用const char*
.
回答by Markus
Alright, thanks a lot already everyone. I think I am starting to get the hang of it, kind of...
好的,已经非常感谢大家了。我想我开始掌握它的窍门了,有点……
First of all I wasn't aware of the fact, that char is just an 8-bit int. Thanks for that clarification.
首先,我不知道这个事实,char 只是一个 8 位 int。感谢您的澄清。
So I understand that, because there are three assignment operators defined for std::string, each with different argument (string, char*, const char*) the right-hand-side of my expression
所以我明白,因为为 std::string 定义了三个赋值运算符,每个运算符都有不同的参数(字符串,char*,const char*),我的表达式的右侧
s=t
doesn't know, which type is has to convert into, since there are multiple, potentially matching (for this assignment to std::string) conversions defined with either
不知道,必须转换成哪种类型,因为有多个潜在匹配(对于此分配给 std::string)转换
operator int () {return 77;};
operator std::string () {return "hello";};
(since char : 8bit int)
(因为字符:8 位整数)
or
或者
operator char* () {return (char*)"hi";};
operator std::string () {return "hello";};
Is that right? So in idiots terms, the left-hand-side of the assignment isn't telling the right-hand-side which type it expects, so rhs has to choose from its options, where one is as good as some other? std::string operator= is being to tolerant for my intents?
那正确吗?所以用白痴的话来说,赋值的左侧并没有告诉右侧它期望哪种类型,所以 rhs 必须从它的选项中进行选择,一个和另一个一样好?std::string operator= 是否容忍我的意图?
So far so good, I thought I got it - but then, why does the following create ambiguity as well?
到目前为止一切顺利,我以为我明白了 - 但是,为什么以下内容也会造成歧义?
using namespace std;
#include <string>
#include <iostream>
class testClass
{
public:
operator float () {return float(77.333);};
operator std::string () {return "hello";};
};
int main()
{
std::string s = "goodday";
testClass t;
s = t;
cout<< " string: "<<s <<endl;
return 0;
}
Now there is only one matching conversion operator defined by me, right? std::string operator= cannot take floats, or can it? Or is float in some way equivalent to some variant of char again?
现在只有一个我定义的匹配转换运算符,对吗?std::string operator= 不能接受浮点数,或者可以吗?或者 float 是否以某种方式再次等同于 char 的某些变体?
I understand the code as 's=' telling the rhs: "give me a string, char* or const char*"
我将代码理解为 's=' 告诉 rhs:“给我一个字符串,char* 或 const char*”
Rhs checks what it can provide given an instance of testClass, and the only match is testClass::operator std::string
Rhs 检查在给定 testClass 实例的情况下它可以提供什么,唯一匹配的是 testClass::operator std::string
Again, thanks for your patience, expertise and time guys - I really appreciate it.
再次感谢你们的耐心、专业知识和时间——我真的很感激。