[英]User-defined conversion function and casting to reference
I am encountering a compilation error for the following code: 我遇到以下代码的编译错误:
class SymbolGroup
{
std::string d_;
public:
SymbolGroup(std::string a):d_(a){}
// explicit operator const std::string&() const { return d_;} // compiles
explicit operator std::string() const { return d_;} // Does not compile
};
inline
bool operator==(const SymbolGroup& lhs, const SymbolGroup& rhs)
{
return static_cast<const std::string&>(lhs) ==
static_cast<const std::string&>(rhs);
}
int main(){
SymbolGroup a("hello");
SymbolGroup b("hello");
if (a==b)
std::cout << "they are the same\n";
return 0;
}
Without the 'const' and '&' in the user-defined type conversion line, it does not compile in g++ (4.8) with --std=c++11 flag: 如果没有用户定义的类型转换行中的'const'和'&',则不能使用--std = c ++ 11标志在g ++(4.8)中编译:
error: invalid initialization of reference of type 'std::string& {aka std::basic_string&}' from expression of type 'const string {aka const std::basic_string}' explicit operator std::string&() const { return d_;} 错误:从类型'const string {aka const std :: basic_string}'表达式的表达式'std :: string&{aka std :: basic_string&}'类型的引用的无效初始化'显式运算符std :: string&()const {return d_; }
The code compiles on Clang both ways. 代码在两个方面编译Clang。 Which compiler is correct? 哪个编译器正确? Should this code compile with operator std::string()
? 这段代码应该用operator std::string()
编译吗?
UPDATE My previous answer was exactly wrong. 更新我以前的回答是完全错误的。 Apologies! 道歉! tldr; tldr; clang is correct to accept the code, gcc is incorrect to reject it. clang接受代码是正确的,gcc拒绝它是不正确的。
First, from [expr.static.cast]: 首先,来自[expr.static.cast]:
An expression e can be explicitly converted to a type T using a static_cast of the form
static_cast<T>(e)
if the declarationT t(e)
; 如果声明T t(e)
,则可以使用static_cast<T>(e)
形式的static_cast<T>(e)
将表达式e显式转换为类型T. is well-formed, for some invented temporary variable t (8.5). 对于一些发明的临时变量t(8.5),其形式良好。
So effectively we're trying to direct-initialize an object of type std::string const&
explicitly from an object of type SymbolGroup const&
. 因此,我们有效地尝试从SymbolGroup const&
类型的对象直接初始化std::string const&
类型的对象。 There is a section specifically on initializing references by a conversion function: "Initialization by conversion function for direct reference binding" [over.match.ref]: 有一节专门用于通过转换函数初始化引用:“通过转换函数初始化直接引用绑定”[over.match.ref]:
Under the conditions specified in 8.5.3, a reference can be bound directly to a glvalue or class prvalue that is the result of applying a conversion function to an initializer expression. 在8.5.3中指定的条件下,引用可以直接绑定到glvalue或类prvalue,它是将转换函数应用于初始化表达式的结果。 Overload resolution is used to select the conversion function to be invoked. 重载分辨率用于选择要调用的转换函数。 Assuming that “ cv1 T” is the underlying type of the reference being initialized, and “ cv S” is the type of the initializer expression, with S a class type, the candidate functions are selected as follows: 假设“ cv1 T”是初始化的引用的基础类型,并且“ cv S”是初始化表达式的类型,S是类类型,候选函数选择如下:
— The conversion functions of S and its base classes are considered. - 考虑S及其基类的转换函数。 Those non-explicit conversion functions that [...] are candidate functions. 那些[...]是候选函数的非显式转换函数。 For direct-initialization, those explicit conversion functions that are not hidden within S and yield type “lvalue reference to cv2 T2” or “ cv2 T2” or “rvalue reference to cv2 T2”, respectively, where T2 is the same type as T or can be converted to type T with a qualification conversion (4.4), are also candidate functions. 对于直接初始化,那些未隐藏在S中的显式转换函数和产生类型“左值引用cv2 T2”或“ cv2 T2”或“rvalue reference to cv2 T2”,其中T2与T的类型相同或者可以转换为带有资格转换(4.4)的类型T,也是候选函数。
The first part doesn't apply since our conversion function is explicit
, so I omitted it. 第一部分不适用,因为我们的转换函数是explicit
,所以我省略了它。 The second part does. 第二部分呢。 We have cv1 T is const std::string
, so our conversion function to std::string
is a candidate function because std::string
can be converted to const std::string
with a qualification conversion. 我们有cv1 T是const std::string
,所以我们对std::string
转换函数是候选函数,因为std::string
可以通过限定转换转换为const std::string
。
gcc is wrong here, and I filed bug 66893 , confirmed by our very own C++ expert and all around good guy Jonathan Wakely as well as the head Clang developer and C++ standard editor Richard Smith (after I thoroughly embarrassed myself filing a Clang bug). gcc在这里是错误的,我提交了错误66893 ,由我们自己的C ++专家和好人Jonathan Wakely以及主管Clang开发人员和C ++标准编辑Richard Smith(在我彻底尴尬地自己提交Clang错误之后)确认。
Well sir, the answer i pretty straightforward. 先生,答案非常简单。 Instead of casting to const reference in return like this: 而不是像这样转换为const引用作为回报:
return static_cast<const std::string&>(lhs) == static_cast<const std::string&>(rhs);
Cast your type to std::string
: 将您的类型转换为std::string
:
return static_cast<std::string>(lhs) == static_cast<std::string>(rhs);
And enjoy working code :) 并享受工作代码:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.