C++ 关系运算符生成器

Nik*_*iou 2 c++ templates

定义<运算符后,您就可以估计其余关系运算符的行为方式。我正在尝试为我的课程实现一种方法。

我想要的是仅定义<和其余的运算符隐式默认。到目前为止我所得到的是这个设计,我将在下面进一步详细说明:

template<typename T>
struct relational
{
    friend bool operator> (T const &lhs, T const &rhs) { return rhs < lhs; }
    friend bool operator==(T const &lhs, T const &rhs) { return !(lhs < rhs || lhs > rhs); }
    friend bool operator!=(T const &lhs, T const &rhs) { return !(rhs == lhs); }
    friend bool operator<=(T const &lhs, T const &rhs) { return !(rhs < lhs); }
    friend bool operator>=(T const &lhs, T const &rhs) { return !(lhs < rhs); }
};
Run Code Online (Sandbox Code Playgroud)

因此,对于实现该运算符的类,<只需继承relational即可使其余运算符默认。

struct foo : relational<foo>
{ 
    // implement < operator here
};
Run Code Online (Sandbox Code Playgroud)
  1. 有没有其他替代方案、更好的设计?
  2. 这段代码里有定时炸弹吗?我假设如果用户想要为其中一个运算符定义自定义实现,重载决策将启动并选择非模板(用户定义)实现。如果情况并非如此(或者我会遇到继承自 的类模板的问题relational),我应该像这样实现运算符吗relational

    // inside the relational struct
    friend bool operator>(relational const &lhs, relational const &rhs)
    { // functions that involve implicit conversion are less favourable in overload resolution
            return (T const&)rhs < (T const&)lhs; 
    }
    
    Run Code Online (Sandbox Code Playgroud)

感谢您的建议,这是代码工作的演示

Jam*_*nze 5

我通常使用从罗伯特·马丁那里学到的技巧来做到这一点。我有一个模板类:

template <typename T>
class ComparisonOperators
{
protected:
    ~ComparisonOperators() {}

public:
    friend bool operator==( T const& lhs, T const& rhs )
    {
        return lhs.compare( rhs ) == 0;
    }
    friend bool operator!=( T const& lhs, T const& rhs )
    {
        return lhs.compare( rhs ) != 0;
    }
    friend bool operator<( T const& lhs, T const& rhs )
    {
        return lhs.compare( rhs ) < 0;
    }
    friend bool operator<=( T const& lhs, T const& rhs )
    {
        return lhs.compare( rhs ) <= 0;
    }
    friend bool operator>( T const& lhs, T const& rhs )
    {
        return lhs.compare( rhs ) > 0;
    }
    friend bool operator>=( T const& lhs, T const& rhs )
    {
        return lhs.compare( rhs ) >= 0;
    }
};
Run Code Online (Sandbox Code Playgroud)

需要运算符的类派生于此:

class Toto : public ComparisonOperators<Toto>
{
    // ...
public:
    //      returns value < 0, == 0 or >0, according to
    //      whether this is <, == or > other.
    int compare( Toto const& other ) const;
};
Run Code Online (Sandbox Code Playgroud)

(我的实现实际上有点复杂,因为它使用一些简单的元编程来调用isEqual,而不是 compare,如果该函数存在。)

编辑:

重新阅读你的问题:这基本上就是你正在做的事情,而且这几乎是这类事情的标准习惯用法。我更喜欢使用诸如 之类的命名函数compare,但这只是个人喜好。然而,处理 的元编程技巧isEqual是值得费心的:这意味着您可以对仅支持相等的类型使用相同的类;当编译器尝试实例化 eg 时,您会收到错误operator<=,但除非有人使用它,否则编译器不会尝试实例化它。通常情况下,它的isEqual实施效率比compare.

编辑2:

对于它的价值:我系统地这样做。我也有 ArithmeticOperators(定义例如++=MixedTypeArithmeticOperators(像上面一样,但是有两种类型,T1它是基类,并且T2它提供了所有运算符的组合)。和 STLIteratorOperators,它基于更合理且更容易实现的东西(基本上是带有函数的 GoF 迭代器isEqual )实现了 STL 迭代器接口。他们节省了大量的样板文件。

编辑3:

最后:我只是查看了工具包中的实际代码。有条件支持isEqual比我记忆中的还要简单:上面的模板类有一个公共成员:

bool isEqual( T const& other ) const
{
    return static_cast< T const* >( this )->compare( other ) == 0;
}
Run Code Online (Sandbox Code Playgroud)

并且operator==只需operator!=使用isEqual,不涉及模板元编程。如果派生类定义了一个isEqual,它会隐藏这个并被使用。如果没有,就用这个。


归档时间:

查看次数:

1561 次

最近记录:

2 年,1 月 前