Error operator+ function

Discussion in 'C++' started by Nephi Immortal, Feb 12, 2011.

  1. I am trying to figure out why C++ Compiler generates an error message
    as saying “3 overloads have similar conversions” It will compile
    without any problem if I comment casting operator function. I still
    need to use casting operator function and add operator function.


    class A {
    public:
    A( unsigned int data ) : m_data( data ) {
    }
    ~A() {
    }

    A( const A& r ) : m_data( r.m_data ) {
    }

    const A& operator=( const A& r ) {
    m_data = r.m_data;
    return *this;
    }

    const A& operator=( const unsigned int data ) {
    m_data = data;
    return *this;
    }

    // Compile without error if you comment below.
    operator unsigned int() {
    return m_data;
    }

    A operator+( const A& r ) {
    A t( m_data );
    t.m_data += r.m_data;
    return t;
    }

    A operator+( const unsigned int data ) {
    A t( m_data );
    t.m_data += data;
    return t;
    }

    A &operator+=( const A& r ) {
    m_data += r.m_data;
    return *this;
    }

    A &operator+=( const unsigned int data ) {
    m_data += data;
    return *this;
    }

    private:
    unsigned int m_data;
    };


    int main () {
    unsigned int x = 1, y = 2;

    A d( x ), d2( y );
    d = d + d2; // OK
    d += d2; // OK

    unsigned int data = d; // OK

    d = d + 7; // ERROR
    d += 7; // OK

    return 0;
    } // end function main

    ------ Build started: Project: MPU_65xx, Configuration: Debug Win32
    ------
    Main.cpp
    c:\ main.cpp(216): error C2666: 'A::eek:perator +' : 3 overloads have
    similar conversions
    c:\main.cpp(46): could be 'A A::eek:perator +(const unsigned
    int)'
    c:\main.cpp(41): or 'A &A::eek:perator +(const A &)'
    or 'built-in C++ operator+(unsigned int, int)'
    while trying to match the argument list '(A, int)'
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped
    ==========
    Nephi Immortal, Feb 12, 2011
    #1
    1. Advertising

  2. Nephi Immortal

    Ian Collins Guest

    On 02/12/11 01:33 PM, Nephi Immortal wrote:
    > I am trying to figure out why C++ Compiler generates an error message
    > as saying “3 overloads have similar conversions” It will compile
    > without any problem if I comment casting operator function. I still
    > need to use casting operator function and add operator function.


    Your problem is very similar to the earlier thread "cout printing and
    function tracing".

    You have to remove the ambiguity. For starters, making the constructor
    from unsigned explicit removes one possible accidental conversion. Then
    you can remove the operator + for unsigned. That leaves only one
    possible sequence of conversions.

    You could also remove the remaining operator + and use a free function:

    A operator+( const A& a, const A& b )
    {
    A t(a);
    t += b;
    return t;
    }

    By the way, there's no point in declaring the unsigned parameters as const.

    --
    Ian Collins
    Ian Collins, Feb 12, 2011
    #2
    1. Advertising

  3. On Feb 11, 7:57 pm, Ian Collins <> wrote:
    > On 02/12/11 01:33 PM, Nephi Immortal wrote:
    >
    > >    I am trying to figure out why C++ Compiler generates an error message
    > > as saying “3 overloads have similar conversions”  It will compile
    > > without any problem if I comment casting operator function.  I still
    > > need to use casting operator function and add operator function.

    >
    > Your problem is very similar to the earlier thread "cout printing and
    > function tracing".
    >
    > You have to remove the ambiguity.  For starters, making the constructor
    > from unsigned explicit removes one possible accidental conversion.  Then
    > you can remove the operator + for unsigned.  That leaves only one
    > possible sequence of conversions.
    >
    > You could also remove the remaining operator + and use a free function:
    >
    > A operator+( const A& a, const A& b )
    > {
    >    A t(a);
    >    t += b;
    >    return t;
    >
    > }
    >
    > By the way, there's no point in declaring the unsigned parameters as const.


    I discovered the solution. If you define “d = d + 7”, then C++
    Compiler will generate an error message. Why? The constant value: 7
    is signed integer by default in the main function’s body. You must
    explicitly convert from signed integer to unsigned integer by doing “d
    = d + ( unsigned int ) 7” or “d = d + 7U” before no error message
    generates by C++ Compiler.
    The alternative option is to add “A operator+( const int data )”
    below “A operator+( const unsigned int data )”.
    You do not need to place any operator functions on the global scope
    since you prefer to treat them as member functions. The performance
    should not be concerned as optimization is doing great job.
    Nephi Immortal, Feb 12, 2011
    #3
  4. Nephi Immortal

    Ian Collins Guest

    On 02/12/11 05:19 PM, Nephi Immortal wrote:
    > On Feb 11, 7:57 pm, Ian Collins<> wrote:
    >> On 02/12/11 01:33 PM, Nephi Immortal wrote:
    >>
    >>> I am trying to figure out why C++ Compiler generates an error message
    >>> as saying “3 overloads have similar conversions” It will compile
    >>> without any problem if I comment casting operator function. I still
    >>> need to use casting operator function and add operator function.

    >>
    >> Your problem is very similar to the earlier thread "cout printing and
    >> function tracing".
    >>
    >> You have to remove the ambiguity. For starters, making the constructor
    >> from unsigned explicit removes one possible accidental conversion. Then
    >> you can remove the operator + for unsigned. That leaves only one
    >> possible sequence of conversions.
    >>
    >> You could also remove the remaining operator + and use a free function:
    >>
    >> A operator+( const A& a, const A& b )
    >> {
    >> A t(a);
    >> t += b;
    >> return t;
    >>
    >> }
    >>
    >> By the way, there's no point in declaring the unsigned parameters as const.

    >
    > I discovered the solution. If you define “d = d + 7”, then C++
    > Compiler will generate an error message. Why?


    I assume you mean "write" rather than define?

    The reason why is presence of the operator unsigned(). Thus d can be
    converted to an unsigned which gives raise to the ambiguity between the
    built in operator +(unsigned, int) and your A::eek:perator+.

    > The constant value: 7
    > is signed integer by default in the main function’s body. You must
    > explicitly convert from signed integer to unsigned integer by doing “d
    > = d + ( unsigned int ) 7” or “d = d + 7U” before no error message
    > generates by C++ Compiler.
    > The alternative option is to add “A operator+( const int data )”
    > below “A operator+( const unsigned int data )”.


    Why add more code when you can also solve the problem by removing code?

    > You do not need to place any operator functions on the global scope
    > since you prefer to treat them as member functions. The performance
    > should not be concerned as optimization is doing great job.


    Whether one uses a free function of a member to implement binary
    operators is largely a matter of choice, performance does not enter into
    the decision. Given an class with an operator +=, either is equally
    valid. Given a set of classes with an operator +=, a simple template
    function can be used for all of them:

    template <typename T>
    const T operator+( const T& a, const T& b )
    {
    return T(a) += b;
    }

    --
    Ian Collins
    Ian Collins, Feb 12, 2011
    #4
  5. Nephi Immortal

    James Kanze Guest

    On Feb 12, 1:57 am, Ian Collins <> wrote:
    > On 02/12/11 01:33 PM, Nephi Immortal wrote:


    > > I am trying to figure out why C++ Compiler generates an error message
    > > as saying “3 overloads have similar conversions” It will compile
    > > without any problem if I comment casting operator function. I still
    > > need to use casting operator function and add operator function.


    > Your problem is very similar to the earlier thread "cout printing and
    > function tracing".


    > You have to remove the ambiguity. For starters, making the constructor
    > from unsigned explicit removes one possible accidental conversion. Then
    > you can remove the operator + for unsigned. That leaves only one
    > possible sequence of conversions.


    But likely not the one he wants.

    > You could also remove the remaining operator + and use a free function:


    > A operator+( const A& a, const A& b )
    > {
    > A t(a);
    > t += b;
    > return t;
    > }


    (For the expression d + 7, where d has type A, and type A has
    both a constructor taking unsigned, and a conversion operator to
    unsigned.)

    How would that remove the ambiguity? You'd still have the two
    possibilities: convert the A to unsigned, and use integer
    arithmetic, or convert the int to A, and use the above. The
    first results in a better match for the first argument, and the
    second a better match for the second, so the expression is
    ambiguous.

    In such cases, the best solution is often to overload all three
    possibilities:

    A operator+( A const& lhs, A const& rhs );
    A operator+( A const& lhs, unsigned rhs );
    A operator+( unsigned lhs, A const& rhs );

    This way, you get exactly what you want. (Somewhere floating
    around I've got a template base class which does this
    automatically if you define an A::eek:perator+=(unsigned rhs)
    member. Something like:

    template< typename DerivedType, typename SecondType >
    class MixedArithmeticOperators
    {
    friend DerivedType operator+(
    DerivedType const& lhs,
    SecondType const& rhs )
    {
    DerivedType result(lhs);
    result += rhs;
    return result;
    }
    friend DerivedType operator+(
    SecondType const& lhs,
    DerivedType const& rhs )
    {
    DerivedType result(rhs);
    result += lhs;
    return result;
    }
    };

    You'd then just derive from MixedArithmeticOperators<A,
    unsigned>.

    --
    James Kanze
    James Kanze, Feb 12, 2011
    #5
  6. Nephi Immortal

    James Kanze Guest

    On Feb 12, 4:19 am, Nephi Immortal <> wrote:
    > On Feb 11, 7:57 pm, Ian Collins <> wrote:
    > > On 02/12/11 01:33 PM, Nephi Immortal wrote:


    > > > I am trying to figure out why C++ Compiler generates an error message
    > > > as saying “3 overloads have similar conversions” It will compile
    > > > without any problem if I comment casting operator function. I still
    > > > need to use casting operator function and add operator function.


    > > Your problem is very similar to the earlier thread "cout printing and
    > > function tracing".


    > > You have to remove the ambiguity. For starters, making the constructor
    > > from unsigned explicit removes one possible accidental conversion. Then
    > > you can remove the operator + for unsigned. That leaves only one
    > > possible sequence of conversions.


    > > You could also remove the remaining operator + and use a free function:


    > > A operator+( const A& a, const A& b )
    > > {
    > > A t(a);
    > > t += b;
    > > return t;
    > > }


    > > By the way, there's no point in declaring the unsigned parameters as const.


    > I discovered the solution. If you define “d = d + 7”, then C++
    > Compiler will generate an error message. Why? The constant value: 7
    > is signed integer by default in the main function’s body. You must
    > explicitly convert from signed integer to unsigned integer by doing “d
    > = d + ( unsigned int ) 7” or “d = d + 7U” before no error message
    > generates by C++ Compiler.


    And what happens if you write 7 + t?

    See my previous posting for the usual solution.

    > The alternative option is to add “A operator+( const int data )”
    > below “A operator+( const unsigned int data )”.
    > You do not need to place any operator functions on the global scope
    > since you prefer to treat them as member functions. The performance
    > should not be concerned as optimization is doing great job.


    Binary arithmetic operators should never be members if the type
    in question supports any type conversions. You want a + b to
    behave in the same way for both a and b; the compiler will not
    consider type conversions for the left hand side if the operator
    is a member.

    What book are you using to learn C++. This is one of the
    basics, generally explained at about the same time operator
    overloading is explained.

    --
    James Kanze
    James Kanze, Feb 12, 2011
    #6
  7. Nephi Immortal

    James Kanze Guest

    On Feb 12, 5:12 am, Ian Collins <> wrote:
    > On 02/12/11 05:19 PM, Nephi Immortal wrote:


    > > I discovered the solution. If you define “d = d + 7”, then C++
    > > Compiler will generate an error message. Why?


    > I assume you mean "write" rather than define?


    > The reason why is presence of the operator unsigned(). Thus d can be
    > converted to an unsigned which gives raise to the ambiguity between the
    > built in operator +(unsigned, int) and your A::eek:perator+.


    I forgot to mention this earlier, but supporting bi-directional
    implicit conversion (from and to the same type) is a good recepe
    for ambiguities all over the place, and should generally be
    avoided.

    > > The constant value: 7
    > > is signed integer by default in the main function’s body. You must
    > > explicitly convert from signed integer to unsigned integer by doing “d
    > > = d + ( unsigned int ) 7” or “d = d + 7U” before no error message
    > > generates by C++ Compiler.
    > > The alternative option is to add “A operator+( const int data )”
    > > below “A operator+( const unsigned int data )”.


    > Why add more code when you can also solve the problem by removing code?


    Probably because suppressing the conversion from unsigned A
    causes the wrong operator+ to be used. More likely, he should
    replace the explicit conversion to unsigned with a named member
    function.

    > > You do not need to place any operator functions on the global scope
    > > since you prefer to treat them as member functions. The performance
    > > should not be concerned as optimization is doing great job.


    > Whether one uses a free function of a member to implement binary
    > operators is largely a matter of choice,


    Not really, when implicit conversions enter into the picture.
    If operator+ is a member, implicit conversions will not be
    considered for the left argument; this lack of orthogonality is
    a serious defect for most types.

    > performance does not enter into
    > the decision. Given an class with an operator +=, either is equally
    > valid. Given a set of classes with an operator +=, a simple template
    > function can be used for all of them:


    > template <typename T>
    > const T operator+( const T& a, const T& b )
    > {
    > return T(a) += b;
    > }


    First, such a template is going to result in an enormous number
    of ambiguities. Second, it results in total uncontrolled
    conversions. I far prefer the Barton and Nackman trick that I
    posted in another response. But if you do want the uncontrolled
    conversions, at least make this function a friend, and define it
    inline in the class, so it won't be found except by ADL. (Note
    that you make it a friend not so that it can access private
    members, but so that you can define it completely within the
    class, so no declarations will be visible outside the class
    unless ADL kicks in.)

    --
    James Kanze
    James Kanze, Feb 12, 2011
    #7
  8. Nephi Immortal

    Öö Tiib Guest

    On Feb 12, 1:10 pm, James Kanze <> wrote:
    > On Feb 12, 1:57 am, Ian Collins <> wrote:
    >
    > > On 02/12/11 01:33 PM, Nephi Immortal wrote:
    > > >    I am trying to figure out why C++ Compiler generates an error message
    > > > as saying “3 overloads have similar conversions”  It will compile
    > > > without any problem if I comment casting operator function.  I still
    > > > need to use casting operator function and add operator function.

    > > Your problem is very similar to the earlier thread "cout printing and
    > > function tracing".
    > > You have to remove the ambiguity.  For starters, making the constructor
    > > from unsigned explicit removes one possible accidental conversion.  Then
    > > you can remove the operator + for unsigned.  That leaves only one
    > > possible sequence of conversions.

    >
    > But likely not the one he wants.
    >
    > > You could also remove the remaining operator + and use a free function:
    > > A operator+( const A& a, const A& b )
    > > {
    > >    A t(a);
    > >    t += b;
    > >    return t;
    > > }

    >
    > (For the expression d + 7, where d has type A, and type A has
    > both a constructor taking unsigned, and a conversion operator to
    > unsigned.)
    >
    > How would that remove the ambiguity?  You'd still have the two
    > possibilities: convert the A to unsigned, and use integer
    > arithmetic, or convert the int to A, and use the above.  The
    > first results in a better match for the first argument, and the
    > second a better match for the second, so the expression is
    > ambiguous.
    >
    > In such cases, the best solution is often to overload all three
    > possibilities:
    >
    >     A operator+( A const& lhs, A const& rhs );
    >     A operator+( A const& lhs, unsigned rhs );
    >     A operator+( unsigned lhs, A const& rhs );
    >
    > This way, you get exactly what you want.  (Somewhere floating
    > around I've got a template base class which does this
    > automatically if you define an A::eek:perator+=(unsigned rhs)
    > member.  Something like:
    >
    >     template< typename DerivedType, typename SecondType >
    >     class MixedArithmeticOperators
    >     {
    >         friend DerivedType operator+(
    >                 DerivedType const& lhs,
    >                 SecondType const& rhs )
    >         {
    >             DerivedType result(lhs);
    >             result += rhs;
    >             return result;
    >         }
    >         friend DerivedType operator+(
    >                 SecondType const& lhs,
    >                 DerivedType const& rhs )
    >         {
    >             DerivedType result(rhs);
    >             result += lhs;
    >             return result;
    >         }
    >     };
    >
    > You'd then just derive from MixedArithmeticOperators<A,
    > unsigned>.


    Seems good, but isn't it simpler to accept parameter by value if you
    are otherwise going to copy it anyway? ...

    template< typename Derived, typename Other >
    class MixedArithmeticOperators
    {
       friend Derived operator+( Derived lhs
    , Other const& rhs )
      {
            lhs += rhs;
            return lhs;
        }

        friend Derived operator+( Other const& lhs
    , Derived rhs )
        {
            rhs += lhs;
           return rhs;
       }
    };
    Öö Tiib, Feb 12, 2011
    #8
  9. Nephi Immortal

    Ian Collins Guest

    On 02/13/11 12:10 AM, James Kanze wrote:
    > On Feb 12, 1:57 am, Ian Collins<> wrote:
    >> On 02/12/11 01:33 PM, Nephi Immortal wrote:

    >
    >>> I am trying to figure out why C++ Compiler generates an error message
    >>> as saying “3 overloads have similar conversions” It will compile
    >>> without any problem if I comment casting operator function. I still
    >>> need to use casting operator function and add operator function.

    >
    >> Your problem is very similar to the earlier thread "cout printing and
    >> function tracing".

    >
    >> You have to remove the ambiguity. For starters, making the constructor
    >> from unsigned explicit removes one possible accidental conversion. Then
    >> you can remove the operator + for unsigned. That leaves only one
    >> possible sequence of conversions.

    >
    > But likely not the one he wants.


    How do you know? Considering he doesn't even test the result! In this
    example, it doesn't matter whether operator+(unsigned, int) or
    A::eek:perator+(const A&) is called.

    >> You could also remove the remaining operator + and use a free function:

    >
    >> A operator+( const A& a, const A& b )
    >> {
    >> A t(a);
    >> t += b;
    >> return t;
    >> }

    >
    > (For the expression d + 7, where d has type A, and type A has
    > both a constructor taking unsigned, and a conversion operator to
    > unsigned.)
    >
    > How would that remove the ambiguity? You'd still have the two
    > possibilities: convert the A to unsigned, and use integer
    > arithmetic, or convert the int to A, and use the above. The
    > first results in a better match for the first argument, and the
    > second a better match for the second, so the expression is
    > ambiguous.


    Not if the constructor from unsigned is explicit.

    --
    Ian Collins
    Ian Collins, Feb 12, 2011
    #9
  10. Nephi Immortal

    James Kanze Guest

    On Feb 12, 6:07 pm, Öö Tiib <> wrote:
    > On Feb 12, 1:10 pm, James Kanze <> wrote:


    [...]
    > > This way, you get exactly what you want. (Somewhere floating
    > > around I've got a template base class which does this
    > > automatically if you define an A::eek:perator+=(unsigned rhs)
    > > member. Something like:


    > > template< typename DerivedType, typename SecondType >
    > > class MixedArithmeticOperators
    > > {
    > > friend DerivedType operator+(
    > > DerivedType const& lhs,
    > > SecondType const& rhs )
    > > {
    > > DerivedType result(lhs);
    > > result += rhs;
    > > return result;
    > > }
    > > friend DerivedType operator+(
    > > SecondType const& lhs,
    > > DerivedType const& rhs )
    > > {
    > > DerivedType result(rhs);
    > > result += lhs;
    > > return result;
    > > }
    > > };


    > > You'd then just derive from MixedArithmeticOperators<A,
    > > unsigned>.


    > Seems good, but isn't it simpler to accept parameter by value
    > if you are otherwise going to copy it anyway? ...


    Maybe. If you like revealing implementation details in the
    interface:).

    Seriously, in this case, you could argue both ways; the fact
    that you copy it here is almost part of the contract (since the
    contract says you use the += operator of DerivedType, and that
    operator requires a non-const object). On the other hand, why
    deviate from the general rule, especially in an inline
    function, where it can make no possible difference with any
    decent compiler.

    (The "general" rule, almost universal in coding guidelines, is
    use reference to const for class types, value for all others.
    Arguably, this is premature optimization, and the rule should
    be: use value, unless the profiler says otherwise. But this
    general rule seems ubiquous, and I suspect that without it, the
    profiler would say otherwise often enough to be more than a
    little bothersome.)

    > template< typename Derived, typename Other >
    > class MixedArithmeticOperators
    > {
    > friend Derived operator+( Derived lhs
    > , Other const& rhs )
    > {
    > lhs += rhs;
    > return lhs;
    > }


    > friend Derived operator+( Other const& lhs
    > , Derived rhs )
    > {
    > rhs += lhs;
    > return rhs;
    > }
    > };


    A third possiblity---one that I've seen more often than the
    above, is:

    template< typename DerivedType, typename SecondType >
    class MixedArithmeticOperators
    {
    friend DerivedType operator+(
    DerivedType const& lhs,
    SecondType const& rhs )
    {
    return DerivedType(lhs) += rhs;
    }
    friend DerivedType operator+(
    SecondType const& lhs,
    DerivedType const& rhs )
    {
    return DerivedType(rhs) += lhs;
    }
    };

    I'll admit that I don't like it too much; I don't like side
    effects in a return statement. But it is the most succinct.

    (BTW: I rather like your formatting, with the comma at the start
    of the line, followed by a space. I've never been able to
    convince anyone else to use it, however, and of course, I do
    follow the local coding guidelines, always. Have you ever
    succeeded in getting this style into the coding guidelines?)

    --
    James Kanze
    James Kanze, Feb 13, 2011
    #10
  11. Nephi Immortal

    James Kanze Guest

    On Feb 12, 7:04 pm, Ian Collins <> wrote:
    > On 02/13/11 12:10 AM, James Kanze wrote:


    [...]
    > >> You have to remove the ambiguity. For starters, making the constructor
    > >> from unsigned explicit removes one possible accidental conversion. Then
    > >> you can remove the operator + for unsigned. That leaves only one
    > >> possible sequence of conversions.


    > > But likely not the one he wants.


    > How do you know? Considering he doesn't even test the result! In this
    > example, it doesn't matter whether operator+(unsigned, int) or
    > A::eek:perator+(const A&) is called.


    Just guessing, but in general, if you define an operator+ for a
    class, you want it to be used when adding values of that class.

    > >> You could also remove the remaining operator + and use a free function:


    > >> A operator+( const A& a, const A& b )
    > >> {
    > >> A t(a);
    > >> t += b;
    > >> return t;
    > >> }


    > > (For the expression d + 7, where d has type A, and type A has
    > > both a constructor taking unsigned, and a conversion operator to
    > > unsigned.)


    > > How would that remove the ambiguity? You'd still have the two
    > > possibilities: convert the A to unsigned, and use integer
    > > arithmetic, or convert the int to A, and use the above. The
    > > first results in a better match for the first argument, and the
    > > second a better match for the second, so the expression is
    > > ambiguous.


    > Not if the constructor from unsigned is explicit.


    If the constructor from unsigned is explicit, then the
    expression is unambiguous, regardless of whether the operator is
    a member or not; there is only one operator+ which can be
    called, and that is the built-in one. The reason for preferring
    a non-member is so that 7 + d has the same behavior at the
    interface level as d + 7. If d + 7 is legal, and 7 + d isn't,
    then you're clearly abusing operator overloading.

    --
    James Kanze
    James Kanze, Feb 13, 2011
    #11
  12. Nephi Immortal

    Öö Tiib Guest

    On Feb 13, 2:33 pm, James Kanze <> wrote:
    > On Feb 12, 6:07 pm, Öö Tiib <> wrote:
    >
    > > On Feb 12, 1:10 pm, James Kanze <> wrote:

    >
    >     [...]
    >
    >
    >
    >
    >
    > > > This way, you get exactly what you want.  (Somewhere floating
    > > > around I've got a template base class which does this
    > > > automatically if you define an A::eek:perator+=(unsigned rhs)
    > > > member.  Something like:
    > > >     template< typename DerivedType, typename SecondType >
    > > >     class MixedArithmeticOperators
    > > >     {
    > > >         friend DerivedType operator+(
    > > >                 DerivedType const& lhs,
    > > >                 SecondType const& rhs )
    > > >         {
    > > >             DerivedType result(lhs);
    > > >             result += rhs;
    > > >             return result;
    > > >         }
    > > >         friend DerivedType operator+(
    > > >                 SecondType const& lhs,
    > > >                 DerivedType const& rhs )
    > > >         {
    > > >             DerivedType result(rhs);
    > > >             result += lhs;
    > > >             return result;
    > > >         }
    > > >     };
    > > > You'd then just derive from MixedArithmeticOperators<A,
    > > > unsigned>.

    > > Seems good, but isn't it simpler to accept parameter by value
    > > if you are otherwise going to copy it anyway? ...

    >
    > Maybe.  If you like revealing implementation details in the
    > interface:).


    I think it does not reveal the details too intrusively. ;-) At least
    usage of the interface remains same be it value or const reference.

    > Seriously, in this case, you could argue both ways; the fact
    > that you copy it here is almost part of the contract (since the
    > contract says you use the += operator of DerivedType, and that
    > operator requires a non-const object).  On the other hand, why
    > deviate from the general rule, especially in an inline
    > function, where it can make no possible difference with any
    > decent compiler.


    My point was that the implementation is slightly simpler because copy
    is made when passing the parameter. The possible C++0x optimizations
    (moving the value) do not matter that much.

    > (The "general" rule, almost universal in coding guidelines, is
    > use reference to const for class types, value for all others.
    > Arguably, this is premature optimization, and the rule should
    > be: use value, unless the profiler says otherwise.  But this
    > general rule seems ubiquous, and I suspect that without it, the
    > profiler would say otherwise often enough to be more than a
    > little bothersome.)
    >


    Yes, that rule is sort of optimization rule. It is likely made to ease
    decision between various ways to pass parameters. It is fine rule in
    general but when local copy is made anyway then passing by value is
    simpler way to make such copy i think. Prefer simplicity when effect
    is same ... it is also sort of omnipresent rule.

    > >  template< typename Derived, typename Other >
    > >  class MixedArithmeticOperators
    > >  {
    > >      friend Derived operator+( Derived lhs
    > >                              , Other const& rhs )
    > >      {
    > >          lhs += rhs;
    > >          return lhs;
    > >      }
    > >      friend Derived operator+( Other const& lhs
    > >                              , Derived rhs )
    > >      {
    > >          rhs += lhs;
    > >          return rhs;
    > >      }
    > >  };

    >
    > A third possiblity---one that I've seen more often than the
    > above, is:
    >
    >     template< typename DerivedType, typename SecondType >
    >     class MixedArithmeticOperators
    >     {
    >         friend DerivedType operator+(
    >                 DerivedType const& lhs,
    >                 SecondType const& rhs )
    >         {
    >             return DerivedType(lhs) += rhs;
    >         }
    >         friend DerivedType operator+(
    >                 SecondType const& lhs,
    >                 DerivedType const& rhs )
    >         {
    >             return DerivedType(rhs) += lhs;
    >         }
    >     };
    >
    > I'll admit that I don't like it too much; I don't like side
    > effects in a return statement.  But it is the most succinct.


    Yes, it is compacted form of your example.

    >
    > (BTW: I rather like your formatting, with the comma at the start
    > of the line, followed by a space.  I've never been able to
    > convince anyone else to use it, however, and of course, I do
    > follow the local coding guidelines, always.  Have you ever
    > succeeded in getting this style into the coding guidelines?)


    Sometimes. Most like it in member initializer list for example. Modern
    monitors are so wide that if a line needs breaking then it is perhaps
    too complex anyway but most agree that operator at start of line makes
    it easier to read. Some just don't care. I would probably like some
    "canonical style" of C++. The C++ source in repository would be kept
    in that style and individual formatting would be then about
    configuring the clients and editors ... just like syntax highlighting
    and coloring.
    Öö Tiib, Feb 14, 2011
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?ISO-8859-1?Q?Mattias_Br=E4ndstr=F6m?=

    operator==, member function or free function

    =?ISO-8859-1?Q?Mattias_Br=E4ndstr=F6m?=, Apr 7, 2005, in forum: C++
    Replies:
    6
    Views:
    2,281
    Donovan Rebbechi
    Apr 7, 2005
  2. Replies:
    1
    Views:
    375
  3. Replies:
    2
    Views:
    676
    Marcus Kwok
    Mar 14, 2007
  4. curiousEngine
    Replies:
    1
    Views:
    1,350
    James Kanze
    May 9, 2008
  5. alex
    Replies:
    3
    Views:
    520
    Richard Cornford
    Dec 28, 2006
Loading...

Share This Page