我正在实现一个迭代器,它迭代生成器函数的结果,而不是内存中的数据结构,如矢量或映射.
通过阅读C++ 17§27.2.3 的最终工作草案,输入迭代器(以及扩展名,大多数其他迭代器) 的解引用运算符的返回类型需要一个前向迭代器作为引用.这适用于迭代器迭代的数据结构中存在的项.但是,因为我没有使用数据结构并且在调用取消引用运算符时计算每个项目,所以我没有返回的有效引用; 当操作员返回时,计算的项目将被销毁.为了解决这个问题,我将计算结果存储在迭代器本身并返回对存储结果的引用.这适用于我的用例,但在与任意用户定义类型一起使用时会有自己的问题.
我可以理解允许迭代器返回引用,但为什么这是非变异迭代器的要求?该标准的编写者是否认为生成器和即时转换是迭代器的有效用例?返回值而不是const引用会导致任何实际的伤害吗?
[编辑]:我问的更多的是出于好奇关于为什么标准被写入事情是这样的,因为我已经有一个非常好的解决方法.
这不是关于模板黑客或处理编译器怪癖的问题。我理解为什么Boost库就是这样。这是关于sinc_piBoost数学库中该函数使用的实际算法的。
该功能sinc(x)等效于sin(x)/x。
在Boost数学库的文档中sinc_pi(),它说“ Taylor系列最初用于确保准确性”。这似乎是荒谬的,因为浮点数的除法运算不会比乘法运算造成更多的精度损失。除非的特定实现存在错误,否则sin的天真的方法
double sinc(double x) {if(x == 0) return 1; else return sin(x)/x;}
Run Code Online (Sandbox Code Playgroud)
似乎会没事的。
我已经测试了这一点,朴素版本与Boost数学工具包中的版本之间的最大相对差异仅为所用类型的epsilon的一半左右(对于float和double而言),这使其与离散化的规模相同错误。此外,此最大差异不会出现在0附近,而是出现在Boost版本使用部分泰勒级数(即abs(x) < epsilon**(1/4))的时间间隔的结尾处。这看起来实际上是泰勒级数逼近,实际上是(非常轻微的)错误,这是由于区间末尾附近的精度损失或由于多次运算引起的反复舍入。
这是我编写的用于测试此结果的程序的结果,该程序对float0到1之间的每一个进行迭代,并计算Boost结果与朴素的结果之间的相对差:
Test for type float:
Max deviation from Boost result is 5.96081e-08 relative difference
equals 0.500029 * epsilon
at x = 0.0185723
which is epsilon ** 0.25003
Run Code Online (Sandbox Code Playgroud)
这是程序的代码。它可以用于对任何浮点类型执行相同的测试,并且运行大约一分钟。
#include <cmath>
#include <iostream>
#include "boost/math/special_functions/sinc.hpp"
template <class T>
T sinc_naive(T x) { using namespace std; if …Run Code Online (Sandbox Code Playgroud)