本文介绍了C ++关系运算符生成器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

定义< 运算符后,您可以估计其余关系运算符的行为。我试图实现一个方法来做我的课。

Once you define the < operator, you can have an estimation of how the rest of relational operators behave. I'm trying to implement a way to do that for my classes.

我想要的只是定义< ,其余的操作符默认默认。我现在到目前为止是这个设计,我将进一步详细说明:

What I want is to define only the < and the rest of the operators to be defaulted implicitly. What I've got so far is this design, which I'll elaborate on further down:

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); }
};

所以对于实现< 运算符,它只是从关系继承,以使其余运算符默认。

So for a class that implements the < operator it would just take inheriting from relational to have the rest of the operators defaulted.

struct foo : relational<foo>
{
    // implement < operator here
};




  1. 是否有其他选择,更好的设计?

  2. 此代码中是否有计时炸弹?我假设如果用户想要为其中一个操作符定义一个自定义实现,重载分辨率将踢并选择非模板(用户定义)实现。如果不是这样(或者我会有类模板继承自关系的问题)我应该实现关系 like this?

  1. Are there any alternatives, better designs ?
  2. Is there a time bomb in this code? I'm assuming that if a user wants to define a custom implementation for one of the operators, the overload resolution would kick and select the non template (user defined) implementation. If that's not the case (or I would have problem with class templates inheriting from relational) should I implement the operators in relational like this ?

// 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;
}


感谢您的意见,这里是一个

Thanks for your advices, here's a demo of the code working

推荐答案

我通常使用我从罗伯特·马丁学到的一个伎俩。
我有一个模板类:

I usually use a trick I learned from Robert Martin to do this.I have a template class:

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;
    }
};

需要运算符的类派生自:

The class which needs the operators derives from this:

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;
};

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

(My implementation is actually a bit more complicated, since ituses some simple meta-programming to call isEqual, rather thancompare, if that function exists.)

编辑:

并重读你的问题:这基本上是你在做什么,这几乎是这个标准的习语那类的东西。我喜欢使用命名的函数,如 compare ,但这只是一个个人偏好。但是,处理 isEqual 的元编程技巧是值得讨论的:它意味着你可以为只支持等式的类型使用相同的类;你会得到一个错误,当编译器试图实例化。 operator< = ,但编译器不会尝试实例化它,除非有人使用它。通常情况下, isEqual 可以比比较更有效地实现。

And rereading your question: this is basically what you're doing, and it's pretty much the standard idiom for this sort of thing. I prefer using named functions like compare, but that is just a personal preference. The meta-programming trick to handle isEqual, however, is worth the bother: it means that you can use the same class for types which only support equality; you'll get an error when the compiler tries to instantiate e.g. operator<=, but the compiler won't try to instantiate it unless someone uses it. And it's often the case the isEqual can be implemented a lot more efficiently than compare.

编辑2:

值得:我这样做是系统的。我还有
ArithmeticOperators (定义例如 + ,以 + = / code>),
MixedTypeArithmeticOperators (像上面,但是有两个
类型, T1 ,它是一个基类, T2 ; it
提供了所有的运算符组合)。和
STLIteratorOperators ,它实现了STL迭代器
接口基于更合理和更容易
实现(基本上,GoF迭代器 isEqual
函数)。他们节省了很多样板。

For what it's worth: I do this systematically. I also haveArithmeticOperators (defining e.g. + in terms of +=),MixedTypeArithmeticOperators (like the above, but with twotypes, T1, for which it is a base class, and T2; itprovides all of the combination of operators). andSTLIteratorOperators, which implements the STL iteratorinterface based on something more rational and easier toimplement (basically, the GoF iterator with an isEqualfunction). They saves a lot of boilerplate.

编辑3:

最后:在我的工具包。
有条件支持 isEqual 甚至比
更简单我记得:上面的模板类有一个公共成员:

And finally: I just looked at the actual code in my toolkit.Conditionally supporting isEqual is even simpler thanI remembered: the template class above has a public member:

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

operator == operator!= 只需使用 isEqual ,不需要
模板元编程。如果派生类
定义了一个 isEqual ,它隐藏了这一个,它被使用。如果
不,这个被使用。

And operator== and operator!= just use isEqual, notemplate meta-programming involved. If the derived classdefines an isEqual, it hides this one, and it gets used. Ifnot, this one gets used.

这篇关于C ++关系运算符生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-16 00:47
查看更多