一旦你定义了 <
运算符,您可以估计其余关系运算符的行为方式。我正在尝试为我的类(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
};
- 是否有任何替代方案和更好的设计?
这段代码中有定时炸弹吗?我假设如果用户想要为其中一个运算符定义自定义实现,则重载解析将启动并选择非模板(用户定义)实现。如果不是这种情况(或者我会遇到从
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/