C++ addition overload ambiguity

前端 未结 5 1256
时光说笑
时光说笑 2020-12-21 13:14

I am coming up against a vexing conundrum in my code base. I can\'t quite tell why my code generates this error, but (for example) std::string does not.

cla         


        
相关标签:
5条回答
  • 2020-12-21 13:39

    The error goes away if you declare the member + const as it should be.

    class String {
    public:
        String(const char*str);
        friend String operator+ ( const String& lval, const char *rval );
        friend String operator+ ( const char *lval, const String& rval );
        String operator+ ( const String& rval ) const; //<-- here
    };
    

    Not sure what's the reason, though. Perhaps it prefers binding arguments to const reference if possible, so the first overload is a better match for the left-hand value and the third overload has a better match for the right-hand value.

    Better explanation. (Must have misread the problem a bit.)


    printf(result);
    

    Don't tell me your String has implicit conversion to const char*... That's evil.

    0 讨论(0)
  • 2020-12-21 13:47

    It is sufficient in this case just to define on operator+:

    String operator+(const String& lval, const String& rval);
    

    Because you provide a constructor taking a char*, a String can be constructed from a char* during the call to operator+. For example:

    String hello = "Hello, ";
    const char* world = "world!";
    
    String helloWorld = hello + world;
    

    A temporary String will be constructed with the contents of the char* world (because your constructor is not explicit), then the two String objects will be passed to operator+.

    0 讨论(0)
  • 2020-12-21 13:54

    You've shown that basic_string has implementations of operator+ corresponding to the second and third operators in your class String. Does basic_string also have an operator corresponding to your first operator [friend String operator+ ( const String& lval, const char *rval );]?

    What happens if you remove this operator?

    0 讨论(0)
  • 2020-12-21 13:59

    The reason for the ambiguity is that one candidate function is better than another candidate function only if none of its parameters are a worse match than the parameters of the other. Consider your two functions:

    friend String operator+(const String&, const char*); // (a)
    String operator+(const String&);                     // (b)
    

    You are calling operator+ with a String and a const char*.

    The second argument, of type const char*, clearly matches (a) better than (b). It is an exact match for (a), but a user-defined conversion is required for (b).

    Therefore, in order for there to be an ambiguity, the first argument must match (b) better than (a).

    The String on the left-hand side of the call to operator+ is not const. Therefore, it matches (b), which is a non-const member function, better than (a), which takes a const String&.

    Therefore, any of the following solutions would remove the ambiguity:

    • Change the member operator+ to be a const member function
    • Change the non-member operator+ to take a String& instead of a const String&
    • Call operator+ with a const String on the left hand side

    Obviously, the first, also suggested by UncleBens, is the best way to go.

    0 讨论(0)
  • 2020-12-21 14:02

    Template and non-template functions follow different rules. The template functions are selected on the actual parameter types, without any conversions being applied. In the case of the non-template (i.e. your code) an implicit conversion can be applied. Thus the templated stuff in basic_string is not ambiguous, but yours is.

    0 讨论(0)
提交回复
热议问题