enable_if仅允许基类

时间:2012-08-18 14:42:25

标签: inheritance c++11 operator-overloading crtp enable-if

我目前正在使用基类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类型

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

非常感谢!

1 个答案:

答案 0 :(得分:2)

/ * SOMETHING * / 可以使用

轻松归档
  1. std::is_same代表Derived和
  2. 的'false'部分
  3. Base
  4. 的'true'部分的帮助器类

    帮助程序类用于确定类是否完全是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
    }