我目前正在使用基类template<class CRTP> Base
和派生类Derived1 : public Base<Derived1>
,Derived2 : public Base<Derived2>
实现一些CRTP ......
数学运算符在Base
中定义,属于CRTP Base<CRTP>::operator+(const CRTP& rhs)
类型,这意味着我们可以向Derived1
但不是Derived1
添加Derived2
}到Derived1
。
此外,我已经定义了运算符Base<CRTP>& Base<CRTP>::operator()()
,这意味着Derived1()
将返回Base<Derived1>&
。
我想知道是否有解决方案可以执行以下操作:
Derived1 = Derived1 + Derived1 : OK
Derived2 = Derived2 + Derived2 : OK
Derived1 = Derived1 + Derived2 : NOT OK
Derived1 = Derived1() + Derived2() : OK
根据最后两行:
我唯一需要做的就是定义一个这样的运算符:
template<class CRTP0, class = typename std::enable_if</* SOMETHING */>::type>
Base<CRTP> Base<CRTP>::operator+(const Base<CRTP0>& rhs)
在enable_if中我想要的是:
true
:如果rhs属于Base
类型false
:如果rhs是Derived
类型这样的事情存在吗?你还有其他解决方案吗?
非常感谢!
答案 0 :(得分:2)
/ * SOMETHING * / 可以使用
轻松归档std::is_same
代表Derived和帮助程序类用于确定类是否完全是Base<?>
:
template <typename> struct IsBase : std::false_type {};
...
template <typename X> struct IsBase<Base<X>> : std::true_type {};
然后我们可以用 / * SOMETHING * / 填写:
std::is_same<Other, Self>::value || IsBase<Other>::value
请注意,这允许Derived1 + Derived2()
。
#include <type_traits>
template <typename> struct IsBase : std::false_type {};
template <typename Self>
struct Base {
Base& operator()() {
return *this;
};
template <typename Other,
typename = typename std::enable_if<std::is_same<Other, Self>::value
|| IsBase<Other>::value>::type>
Self operator+(const Other& other) const {
return static_cast<const Self&>(*this);
}
};
template <typename X> struct IsBase<Base<X>> : std::true_type {};
struct D1 : Base<D1> {};
struct D2 : Base<D2> {};
int main() {
D1 d1;
D2 d2;
d1 + d1; // ok
d2 + d2; // ok
d1() + d2(); // ok
d1 + d2; // error
}