c++ - User-defined conversion function and casting to reference -


i encountering compilation error 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_;} // 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 same\n";    return 0; } 

without 'const' , '&' in user-defined type conversion line, not compile in g++ (4.8) --std=c++11 flag:

error: invalid initialization of reference of type ‘std::string& {aka std::basic_string&}’ expression of type ‘const string {aka const std::basic_string}’ explicit operator std::string&() const { return d_;}

the code compiles on clang both ways. compiler correct? should code compile operator std::string()?

update previous answer wrong. apologies! tldr; clang correct accept code, gcc incorrect reject it.


first, [expr.static.cast]:

an expression e can explicitly converted type t using static_cast of form static_cast<t>(e) if declaration t t(e); well-formed, invented temporary variable t (8.5).

so we're trying direct-initialize object of type std::string const& explicitly object of type symbolgroup const&. there section on initializing references conversion function: "initialization conversion function direct reference binding" [over.match.ref]:

under conditions specified in 8.5.3, reference can bound directly glvalue or class prvalue result of applying conversion function initializer expression. overload resolution used select conversion function invoked. assuming “cv1 t” underlying type of reference being initialized, , “cv s” type of initializer expression, s class type, candidate functions selected follows:

— conversion functions of s , base classes considered. non-explicit conversion functions [...] candidate functions. direct-initialization, explicit conversion functions not hidden within s , yield type “lvalue reference cv2 t2” or “cv2 t2” or “rvalue reference cv2 t2”, respectively, t2 same type t or can converted type t qualification conversion (4.4), candidate functions.

the first part doesn't apply since our conversion function explicit, omitted it. second part does. have cv1 t const std::string, our conversion function std::string candidate function because std::string can converted const std::string qualification conversion.


gcc wrong here, , filed bug 66893, confirmed our own c++ expert , around guy jonathan wakely head clang developer , c++ standard editor richard smith (after thoroughly embarrassed myself filing clang bug).


Comments