1

我目前正在使用基类template<class CRTP> Base和派生类实现一些 CRTP Derived1 : public Base<Derived1>Derived2 : public Base<Derived2>...

数学运算符在中定义,Base并且属于CRTP Base<CRTP>::operator+(const CRTP& rhs)那种意味着我们可以将 a 添加Derived1到 aDerived1但不能将 a 添加到Derived2a 的类型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类型

存在这样的事情吗?您有其他解决方案吗?

非常感谢你 !

4

1 回答 1

2

/ * SOMETHING */可以很容易地使用

  1. std::is_same对于 Derived 和
  2. Base 的“真实”部分的辅助类

辅助类是判断一个类是否正好是 a 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().


示例:http: //ideone.com/OGt0Q

#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
}
于 2012-08-18T19:57:42.577 回答