考虑以下最小示例:
#include <range/v3/all.hpp>
#include <iostream>
namespace rng = ranges::v3;
int main()
{
std::vector<int> v { 6, 2, 3, 4, 5, 6 };
auto f = [](auto a, auto b) { return a*0.3 + b*0.7;};
auto rng = v | rng::view::partial_sum(f);
for(auto i : rng)
{
std::cout<<i<<" ";
}
}
这输出
6 3 2 3 4 5
我本来希望在这里看到双数,但结果显然是整数。这与 的行为相反view::transform
。
这样做的原因是因为在实现中,running-sum 值具有对应于源范围的类型:
semiregular_t<range_value_type_t<Rng>> sum_;
这是故意的还是错误的?
讨论:我看到在尝试获取有效返回类型时遇到了麻烦,因为转换函数同时使用源范围和结果范围作为参数并产生返回类型。下一个应用程序使用 source-range-type 和这个返回类型来产生另一个(可能不同的)返回类型,依此类推。
这样,原则上,将源值类型与转换函数的结果类型重复链接。仅当结果类型“收敛”到所有其他中间结果都可以转换为的特定类型时,这种重复迭代才会产生可用的东西(在上面的示例中,这种类型是double
,在第一次调用转换函数之后已经获得)。
有了这个观察,人们可以提出一种解决方法:应用二进制变换函数给定的次数,并使用common_type
结果范围的 as 值类型(如果发现收敛,过早停止)。在最简单的情况下,迭代次数只有一次。如果这个迭代没有导致一些合理的事情,人们仍然可以求助于源值类型(或编译器错误)。
为了清楚起见,这里是上面示例的应用程序:
First iteration : f(int,int) -> yields "double"
Second iteration: f(int,double) -> yields "double"
Third iteration : f(int,double) -> yields "double"
在第三次迭代之后,模式收敛,所以停止并选择 common-typedouble
作为返回范围的 value_type。
我不确定这种方法在所有理论情况下是否完全有效,但至少它在第一个示例中给出了两倍——我想这是每个人都强烈期待的。