C++ 关系运算符生成器

标签 c++ templates

一旦你定义了 <运算符,您可以估计其余关系运算符的行为方式。我正在尝试为我的类(class)实现一种方法。

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

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

因此对于实现 < 的类运算符它只需要继承自 relational让其余的运营商违约。

struct foo : relational<foo>
{ 
    // implement < operator here
};
  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; 
    }
    

感谢您的建议,这里是demo of the code working

最佳答案

我通常使用从 Robert Martin 那里学到的技巧来做到这一点。 我有一个模板类:

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

需要运算符的类派生自:

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

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

编辑:

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

编辑 2:

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

编辑 3:

最后:我只是查看了工具包中的实际代码。 有条件支持isEqual甚至比 我想起来了:上面的模板类有一个公共(public)成员:

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

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

关于C++ 关系运算符生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23388739/

相关文章:

c++ - 我怎么知道 boost::regex_replace 是否进行了更改?

c++ - Qt : After installation of VS2012 LNK1123 failure during conversion to COFF

javascript - 通过 ajax 调用在 Flask 中渲染模板

c++ - 使用声明的模板化参数实例化嵌套类模板

c++ - 如何获得可调用类型的签名?

c++ - 在成员变量中使用模板类作为模板模板参数时出错

c++ - 构造函数模板

c++ - 内存静态函数 vs 成员函数

c++ - 无法导出模板函数

可变长度的 C++ 数组不起作用