我试图将模板化成员函数的定义和声明从基类转移到派生类。问题是这些函数中的某些行为取决于类,基本上是静态多态性。建议我使用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>> {};
答案 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
}
答案 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
进行同样的操作,以有效地将两者置于层次结构中的同一级别。