可以重构一个重载的运算符到一个非成员函数中断任何代码? [英] Can refactoring an overloaded operator into a non-member function break any code?

本文介绍了可以重构一个重载的运算符到一个非成员函数中断任何代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一个包含重载添加运算符的旧类模板 + = +

Consider a legacy class template with overloaded addition operators += and +

template<class T>
class X
{
public:
    X() = default;
    /* implicict */ X(T v): val(v) {}

    X<T>& operator+=(X<T> const& rhs)       { val += rhs.val; return *this; }
    X<T>  operator+ (X<T> const& rhs) const { return X<T>(*this) += rhs;    } 

private:
    T val;
};

在代码审查后,观察到 + 可以用 + = 来实现,所以为什么不使它成为非成员(并保证左右参数对称)?

Upon code review, it is observed that + is implementable in terms of +=, so why not make it a non-member (and have guaranteed symmetry for left and right arguments)?

template<class T>
class X
{
public:
    X() = default;
    /* implicit */ X(T v): val(v) {}

    X<T>& operator+=(X<T> const& rhs)       { val += rhs.val; return *this; }

private:
    T val;
}; 

template<class T>
X<T> operator+(X<T> const& lhs, X<T> const& rhs)
{ 
    return X<T>(lhs) += rhs; 
}


$ b < + 和 + = 保留其原始的语义含义。

It look safe enough, because all valid expression using + and += retain their original semantic meaning.

问题:可以将成员函数中运算符+ 成员函数中断任何代码?

Question: can the refactoring of operator+ from a member function into a non-member function break any code?

折断定义(最差到最好)

Definition of breakage (worst to best)


  • 新代码将编译

  • 新代码将默认调用不同的<$
  • c $ c> operator + (通过ADL从基类或关联的命名空间中拖拽)
  • new code will compile that did not compile under the old scenario
  • old code will not compile that did compile under the old scenario
  • new code will silently call a different operator+ (from base class or associated namespace dragged in through ADL)

推荐答案

摘要



答案是,是的,总会有破损。基本成分是函数模板参数扣除不考虑隐式转换。我们考虑三种情况,覆盖了重载运算符可以采用的三种语法形式。

Summary

The answer is, yes, there will always be breakage. The essential ingredient is that function template argument deduction does not consider implicit conversions. We consider three scenarios, covering the three syntactic forms that an overloaded operator can take.

这里我们使用 X 本身。但是即使我们使得构造函数显式,用户可以将 X 的类添加到< c $ c> C T ,其包含形式运算符X ()const 的隐式转换。

Here we use an implicit constructor inside X<T> itself. But even if we made that constructor explicit, users could add to the namespace of X<T> a class C<T> that contains an implicit conversion of the form operator X<T>() const. The scenarios below would continue to hold in that case.

一个非成员函数打破了最小的意义,因为它将允许lhs参数隐式转换,不能编译用于类模板的成员函数。非成员函数模板破坏了对rhs参数的隐式转换。

A non-member friend function breaks the least in the sense that it will allow lhs argument implicit conversions that would not compile for a class template's member function. The non-member function template breaks the implicit conversion on rhs arguments.

template<class T>
class X
{
public:
    /* implicit */ X(T val) { /* bla */ }
//...
    X<T> operator+(X<T> const& rhs) { /* bla */ }
//...
};

此代码将允许像

T t;
X<T> x;
x + t;  // OK, implicit conversion on non-deduced rhs
t + x;  // ERROR, no implicit conversion on deduced this pointer



非成员友函数



Non-member friend function

template<class T>
class X
{
public:
    /* implicit */ X(T val) { /* bla */ }
//...
    friend 
    X<T> operator+(X<T> const& lhs, X<T> const& rhs) { /* bla */ }
//...
};

由于 friend 函数不是模板,没有参数扣除发生,并且lhs和rhs参数考虑隐式转换

Since the friend function is a not a template, no argument deduction takes place and both the lhs and rhs argument consider implicit conversions

T t;
X<T> x;
x + t;  // OK, implicit conversion on rhs
t + x;  // OK, implicit conversion on lhs



非成员函数模板



Non-member function template

template<class T>
class X
{
public:
    /* implicit */ X(T val) { /* bla */ }
//...
};

template<class T> 
X<T> operator+(X<T> const& lhs, X<T> const& rhs) { /* bla */ }


$ b b

在这种情况下,lhs和rhs参数都要经过参数推导,并且不考虑隐式转换:

In this case, both the lhs and rhs arguments undergo argument deduction, and neither takes implicit conversions into account:

T t;
X<T> x;
x + t;  // ERROR, no implicit conversion on rhs
t + x;  // ERROR, no implicit conversion on lhs

这篇关于可以重构一个重载的运算符到一个非成员函数中断任何代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆