我有一个数学图书馆。在这个库中,我有在单纯形空间中操作超平面的函数,以便我可以以各种方式对它们进行排序。
事实证明,这些超平面可以在不同的上下文中表示不同的事物。虽然数学是相同的,但在每种情况下,超平面意味着不同的事物,并且与不同的数据结构相关联。
能够编写代码来操作一次超平面,但允许它们处理不同的数据结构,这对我来说是有利的。
下面是一个简化的示例,试图解释我正在尝试做的事情:
// Assume this struct represent my hyperplane, or whatever
// construct I want to be able to manipulate.
struct Math {
int x;
};
// Here is my function `foo` which expects a range of Math. It does
// some work on it, and re-arranges it as it is useful to me.
template <typename It>
void foo(It begin, It end) {
while (begin < end) {
--end;
if (begin->x < end->x)
std::iter_swap(begin, end);
++begin;
}
}
template <typename Range>
void foo(Range & r) {
foo(ranges::begin(r), ranges::end(r));
}
这基本上是我的基础功能,这对于使用我的超平面的每个附加类(或者,在本例中为Math
类)都是常见的。
现在在我图书馆的其他部分,我的类看起来像这样:
struct Something {
int additional_metadata;
Math contextual_name_for_math;
};
struct SomethingElse {
double other_metadata;
std::vector<int> some_other_metadata;
Math another_different_contextual_name;
};
现在我需要能够应用foo
到这些类的范围,并根据Math
它们包含的属性重新排列它们。同时:
foo
不知道Math
每个类中的上下文名称。foo
不关心存在的其他元数据。
我想写的是这样的:
// Create data
std::vector<Something> S{{1,{2}},{3,{4}},{5,{6}}};
// Transform data in to view of Math, so that 'foo' can work on it
auto S_as_math = S | ranges::view::transform(
// I guess I can remove the consts here, although `foo` does not
// really need to alter the values, it only shuffles things around.
[](auto const& s) -> Math const& { return s.contextual_name_for_math; }
);
// Do work inline on the view, but hopefully on the underlying S too.
foo(S_as_math);
// Print results.
for (auto s : S) {
std::cout << '(' << s.additional_metadata << ", "
<< s.contextual_name_for_math.x << ")\n";
}
std::cout << "\n";
// expected, keeps Math and associated metadata together:
//
// (5, 6)
// (3, 4)
// (1, 2)
//
// NOT WANTED, only shuffles Math with no regard for metadata:
//
// (1, 6)
// (3, 4)
// (5, 2)
目前,我通过在取消引用时将boost::transform_iterator
s 传递给foo
提取Math
组件,并使用内部的自定义实现来执行此操作,该iter_swap
内部实现foo
能够知道它是否被传递了代理迭代器并始终交换底层原件。这达到了我想要的。
我很好奇这是否可以使用ranges-v3
. const
目前,如果我删除用于解包类的 lambda中的 s,则我能够编译此示例Something
,但随后foo
仅对 s 进行洗牌,Math
而不将它们与其元数据保持在一起。