【发布时间】:2021-10-22 12:13:40
【问题描述】:
我有以下 CRTP 基类:
template <typename T, template <typename> typename CRTPType>
struct enable_crtp {
auto underlying() -> T& { return static_cast<T&>(*this); }
auto underlying() const -> const T& {
return static_cast<const T&>(*this);
}
};
这种类型的类完美无缺:
template<typename Derived>
class BaseA : public enable_crtp<Derived, BaseA> {
public:
void DoA() {
this->underlying().DoAImpl();
}
private:
friend Derived;
};
class ImplA : public BaseA<ImplA> {
void DoAImpl() {
// do something
}
friend BaseA<ImplA>;
};
但是有没有办法让它与非类型模板类一起工作?像这样的:
template<template<size_t> typename Derived>
class BaseB : public enable_crtp<Derived<size_t>, BaseB> {
^ compile error, template argument for non-type
template parameter must be an expression
void DoB() {
this->underlying().DoBImpl();
}
}
对于真正的问题,我有一个IntegralImageCalculator,它将遍历图像像素以根据其i-th order 累加总和:
template <size_t Order>
class IntegralImageCalculator;
template <>
class IntegralImageCalculator<1> {
void Iterate(cv::Mat& input) {
// Duplicate code
// ...
cv::Mat integral_1st_order;
cv::integral(input, integral_1st_order);
input.forEach<double>(
[&integral_1st_order, this](double& pixel, const int* position) {
Process(integral_1st_order, pixel, position);
});
// Duplicate code
// ...
}
void Process(const cv::Mat& integral_1st_order,
double& pixel,
const int* position) {
// derived class must implement this
}
};
template <>
class IntegralImageCalculator<2> {
void Iterate(cv::Mat& input) {
// Duplicate code
// ...
cv::Mat integral_1st_order;
cv::Mat integral_2nd_order;
cv::integral(input, integral_1st_order, integral_2nd_order);
input.forEach<double>(
[&integral_1st_order, this](double& pixel, const int* position) {
Process(integral_1st_order, integral_2nd_order, pixel, position);
});
// Duplicate code
// ...
}
void Process(const cv::Mat& integral_1st_order,
const cv::Mat& integral_2nd_order,
double& pixel,
const int* position) {
// derived class must implement this
}
};
如您所见,每个订单都有一个额外的求和矩阵。此外,派生类有很多重复代码和特定代码。我想知道是否有办法用 CRTP 解决它们。
【问题讨论】:
-
为什么需要
CRTPType模板参数?在您的示例中,未使用它。如果你真的需要它,为什么不通过BaseA<Derived>而不是BaseA? -
一方面,你的编译器是对的;
Derived<size_t>不是您的模板的有效实例化。另一方面,您是否考虑过如何将IntegralImageCalculator<1>定义为BaseB的实例化作为基类?1如何与enable_crtp通信? (在这种情况下,向前跳过可能是一个有用的技巧 - 只是不要忘记回顾您在某些时候跳过的内容。) -
@Evg 我已经更新了代码,诀窍是摆脱菱形继承,您可以在这里查看更多内容fluentcpp.com/2017/05/19/crtp-helper
-
我建议将钻石继承添加到您的问题中。
-
fluentcpp 链接没有任何意义。介绍性示例is broken。 CRTP 根本不是这样工作的。
template <typename T> struct NumericalFunctions : crtp<T>与我们所知道和喜爱的 CRTP 无关。我建议不要关注那个页面。