我经常遇到需要从数据源创建选择,操纵选择并将更改反馈回原始数据源的情况。像
这样的东西#include <vector>
void manipulate(std::vector<int> &vector) {
// Manipulate vector...
}
int main() {
// Data source
std::vector<int> dataSource{1, 2, 3, 4};
// Select every second entry
std::vector<int> selection{v[0], v[2]};
// Manipulate selection
manipulate(selection);
// Feed data back to the data source
dataSource[0] = selection[0];
dataSource[2] = selection[1];
return 0;
}
为了自动化将数据反馈到数据源的过程,我可以将选择更改为指针或引用的向量(使用std::reference_wrapper
)并将其传递给操作其参数的函数。或者,我可以创建一个类ObservableVector
,它将数据源保存为成员,并将对其所做的所有更改传播到数据源。但是,在这两种情况下,我都需要更改manipulate
的签名以接受指针向量或ObservableVector
。我是否有机会保留原始manipulate
函数(无需创建包装函数)并仍然自动将数据反馈回原始源?
答案 0 :(得分:2)
查看range
库,例如Boost.Range。可以从容器创建范围以包含容器的子集,例如,容器的子集。每个第n个元素,或包含与谓词对象匹配的所有元素的范围。有了它,很容易组成复杂的操作。以下是一些示例代码,它迭代容器的每个第二个元素,过滤它然后计算一些东西
using namespace boost::adaptors;
using namespace boost;
// assume we have a predicate int -> bool
bool pred(int x);
// some function which transforms each element
int computation(int);
std::vector<int> elements = // ...
auto everySecondElement = elements | strided(2);
auto filtered = everySecondElement | filtered(pred);
transform( filtered, filtered.begin(), computation);
这更像是一种功能编程风格,它使范围处理的组合变得非常简单和富有表现力。它可能需要更改您的操作函数,但我认为使用范围库可以极大地改进C ++代码。
答案 1 :(得分:0)
您可以将逻辑包装成一个函数,例如:
template <typename T, typename F>
void manipulate_selection(std::vector<T>& v,
F f,
const std::vector<std::size_t>& indexes)
{
std::vector<T> selection;
// Select every second entry
selection.reserve(indexes.size());
for (auto index : indexes) {
selection.pusk_back(v[index]);
}
// Manipulate selection
f(selection);
// Feed data back to the data source
for (std::size_t i = 0; i != indexes.size(); ++i) {
v[indexes[i]] = selection[i];
}
}
然后使用它:
manipulate_selection(dataSource, manipulate, {0, 2});