简体   繁体   English

用户定义的转换函数和转换引用

[英]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 declaration T 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM