考虑以下最简示例:
在第三次迭代后,模式会收敛,因此停止并选择常见类型
我不确定这种方法在所有理论情况下是否完全有效,但至少它在第一个例子中给出了一个双精度浮点数--我想这正是每个人强烈期望的。
#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
的行为相反。
原因在于,在实现中,运行总和的值的类型对应于源范围:
semiregular_t<range_value_type_t<Rng>> sum_;
这是故意的还是一个错误?
讨论:当试图获得有效的返回类型时,我看到了一个人在尝试使用源范围和结果范围作为参数,并生成返回类型的转换函数时遇到的问题。下一个应用程序使用源范围类型和此返回类型来产生另一种(可能不同的)返回类型,以此类推。
因此,原则上,一个人正在重复地将源值类型与转换函数的结果类型链接起来。只有当结果类型“收敛”到特定类型时,才能使用这种重复迭代的东西,所有其他中间结果都可以转换为该类型(在上面的示例中,该类型已在转换函数的第一次调用后获得,即double
)。
通过这个观察,我们可以提出一个解决方法:多次应用二进制转换函数,然后使用common_type
作为结果范围的值类型(如果找到收敛,则提前停止)。在最简单的情况下,迭代次数只有一次。如果这次迭代没有导致合理的结果,仍然可以使用源值类型(或编译器错误)。
为了清楚起见,这里是上面示例的应用:
First iteration : f(int,int) -> yields "double"
Second iteration: f(int,double) -> yields "double"
Third iteration : f(int,double) -> yields "double"
在第三次迭代后,模式会收敛,因此停止并选择常见类型
double
作为返回范围的value_type。我不确定这种方法在所有理论情况下是否完全有效,但至少它在第一个例子中给出了一个双精度浮点数--我想这正是每个人强烈期望的。