Fruit <- c(rep("Apple",3),rep("Orange",5))
Bug <- c("worm","spider","spider","worm","worm","worm","worm","spider")
group <- rep(LETTERS[1:2], each = 4)
df <- data.frame(Fruit,Bug, group)
表示像素类型为class Frame<P>
的图像。由于底层数据缓冲区格式具有多种灵活性,迭代其像素的算法非常重要。
P
我希望能够同时调用template <typename P, bool RM = true> // P is pixel type; RM = is_row_major
class Frame {
// ...
template<typename F>
void iterate(F f) { // iterate in a way that is performant for this buffer
if (stride == (RM ? size.w : size.h)) {
auto n = size.area();
for (index_t k = 0; k < n; k++) {
f(view[k]);
}
}
else {
auto s = static_cast<index_t>(stride)*(RM ? size.h : size.w);
for (index_t k0 = 0; k0 < s; k0 += stride) {
auto m = k0 + (RM ? size.w : size.h);
for (index_t k = k0; k < m; k++) {
f(view[k]);
}
}
}
}
}
和iterate(fc) const
(分别使用lambda签名iterate(f)
和fc(const P&)
)。我可以复制整个函数体并将f(P&)
附加到签名上,但有更好的方法吗?
答案 0 :(得分:1)
无法推断出成员函数的const
。但是,使用转发引用允许推断函数参数的cost
。因此,您可以委托将对象类型作为参数并转发所有其他参数的函数。这样重复的代码变得微不足道。如果该功能需要访问private
或protected
成员,您只需将其设为(可能是private
)static
成员:
template <typename T, bool PM = true>
class Frame {
template <typename F1, typename F2>
static void iterateTogether(F1&& f1, F2&& f2) {
// actual implementation goes here
}
public:
template <typename F2>
void iterateTogether(F2&& other){
iterateTogether(*this, std::forward<F2>(other));
}
// ...
};
上面使用的实现还允许参数的不同const
。如果你想将参数限制为真正只是Frame
的特化,你需要约束函数,但这很容易完成。
我个人的偏好是无论如何只有琐碎的成员,并将任何非平凡的任务委托给通用算法。我的偏好是类只维护它们的不变量,有趣的用途是通过算法实现的。