Inheritance 如果仅允许基类,则启用\u

Inheritance 如果仅允许基类,则启用\u,inheritance,c++11,operator-overloading,crtp,enable-if,Inheritance,C++11,Operator Overloading,Crtp,Enable If,我目前正在用基类模板库和派生类Derived1:public-base,Derived2:public-base实现一些CRTP 数学运算符在Base中定义,属于crtpbase::operator+(const-CRTP&rhs)类型,这意味着我们可以将Derived1添加到Derived1中,但不能将Derived2添加到Derived1中 此外,我还定义了操作符Base&Base::operator()(),这意味着Derived1()将返回Base& 我想知道是否有一种解决方案可以做到以

我目前正在用基类
模板库
和派生类
Derived1:public-base
Derived2:public-base
实现一些CRTP

数学运算符在
Base
中定义,属于
crtpbase::operator+(const-CRTP&rhs)
类型,这意味着我们可以将
Derived1
添加到
Derived1
中,但不能将
Derived2
添加到
Derived1

此外,我还定义了操作符
Base&Base::operator()()
,这意味着
Derived1()
将返回
Base&

我想知道是否有一种解决方案可以做到以下几点:

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)
模板
Base Base::运算符+(常量Base和rhs)
在enable_中,如果我想要以下内容:

  • true
    :如果rhs属于
    Base
    类型
  • false
    :如果rhs是派生的
    类型
这样的事情存在吗?你还有别的解决办法吗

多谢各位

可以使用

  • std::对于派生和
  • 基类“true”部分的帮助器类
  • helper类用于确定类是否正是

    template <typename> struct IsBase : std::false_type {};
    ...
    template <typename X> struct IsBase<Base<X>> : std::true_type {};
    
    std::is_same<Other, Self>::value || IsBase<Other>::value
    
    #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
    }