继承通用成员函数

时间:2019-07-18 15:45:46

标签: c++ c++17 crtp member-functions

我试图将模板化成员函数的定义和声明从基类转移到派生类。问题是这些函数中的某些行为取决于类,基本上是静态多态性。建议我使用CRTP,这在大多数情况下效果很好。 但是,如果我想从已经从我的CRTP基类继承的类继承,则会遇到问题。考虑以下代码:

template<typename Derived>
struct CRTP
{
    template<typename TypeRHS>
    Derived& operator+=(const TypeRHS& rhs) 
    {
        // do something
        return static_cast<Derived&>(*this);
    }
};

template<typename T>
struct Derived : public CRTP<Derived<T>> {};

template<typename T>
struct DerivedDerived : public Derived<T> {};

如果我在+=上呼叫DerivedDerived<T>,它将返回Derived<T>的类型。有什么办法可以解决这个问题。我只是想避免在所有类中重新声明/重新定义所有成员函数。就免费函数而言,我只是对它们进行了模板化,但是事实证明成员函数是一个问题。

我已经用布莱恩的建议更新了我的问题。请注意,多重继承导致应调用哪个函数的不确定性-来自CRTP<DerivedDerived<T>>的函数或来自Derived<T>的函数:

template<typename T>
struct DerivedDerived : public Derived<T>, public CRTP<DerivedDerived<T>> {};

3 个答案:

答案 0 :(得分:1)

您需要一个由Derived派生的CRTP,以供DerivedDerived使用

template<typename T>
struct CRTP
{
    template<typename TypeRHS>
    T& operator+=(const TypeRHS& rhs) 
    {
        // do something
        return static_cast<T&>(*this);
    }
};

template<typename T>
struct Derived : public CRTP<Derived<T>> {
};

template<typename T>
struct CRTPForDerived : public Derived<T>
{
    template<typename TypeRHS>
    T& operator+=(const TypeRHS& rhs) 
    {
        // do something
        return static_cast<T&>(*this);
    }
};

template<typename T>
struct DerivedDerived : public CRTPForDerived<DerivedDerived<T> > 
{};

答案 1 :(得分:1)

对于算术运算符的特定情况,您可以通过在类/结构之外声明该运算符来解决该问题。在这种情况下,不需要CRTP构造:

#include <type_traits>

// Replaces template<typename> struct CRTP;
struct MyOperatorsBase {

};

template<typename T>
struct Derived : public MyOperatorsBase {

};

template<typename T>
struct DerivedDerived : public Derived<T> {

};

// Overload "a += b" defined only if "a" derives from MyOperatorsBase.
template<typename RetType, typename RhsType>
std::enable_if_t<std::is_base_of_v<MyOperatorsBase,RetType>,RetType&> operator +=(RetType& lhs, const RhsType& rhs) {
    // do something.
    return lhs; // no downcasting static_cast needed, which is nice
}

Live demo

答案 2 :(得分:0)

对于将来的读者,我能想到的最通用和模块化的解决方案实际上是将需要在pyscript中继承的相关部分从$> cat /home/me/bin/pyscript #!/bin/bash # a.py needs module pandas in /foo/bar export PYTHONPATH=/foo/bar cd /Users/Esel/Documents/x/y/z || exit python a.py $> chmod ug+rx /home/me/bin/pyscript $> cat /var/spool/cron/crontabs/me ... * * * * * /home/me/bin/pyscript 分离到各自的类中,然后将{{1 }}可以继承CRTP类以及CRTP类,然后可以对DerivedDerived进行同样的操作,以有效地将两者置于层次结构中的同一级别。