我编写了一个类似于迭代器的RandIt类(下面的代码),但只要取消引用就会返回随机整数。主要用例是使用随机数据初始化向量,如
std::vector<int> v(RandIt<0,99>{}, RandIt<0,99>{50});
生成0到99之间的50个数字。
typedef RandIt::iterator_category
是std::random_access_iterator_tag
,因为
std::distance
分配合适的空间来构建。否则使用emplace_back
,重新分配和复制。std::distance
的RandomAccessIterator作为常量时间,而不是在循环中递增和测试。然而,这是一个谎言,因为取消引用RandIt会返回int
的值,并且ForwardIterators和better都需要返回对内存中对象的引用。
(由于ForwardIterator的“多通道保证”失败也可能是谎言:再次检查序列会产生不同的结果。但cppreference给出“正式”版本
表达式
(void)++It(a), *a
等同于表达式*a
对于某些“等效”值,似乎是真的。)
因此,我绝对违反了规则,声称自己不是。尽管如此,它似乎有效。
这会咬我吗?说谎的潜在影响是什么?
#include <random>
#include <iterator>
template <int min, int max>
struct RandIt {
typedef int difference_type;
typedef int value_type;
typedef const int* pointer;
typedef const int& reference;
typedef std::random_access_iterator_tag iterator_category; // this is a lie
static std::knuth_b rng;
static std::uniform_int_distribution<int> idist;
int i;
explicit RandIt(int i = 0) : i{i} {}
int operator*() const {return idist(rng);}
int operator[](int) const {return idist(rng);}
RandIt& operator++() {++i; return *this;}
RandIt operator++(int) {return RandIt{i++};}
RandIt& operator--() {--i; return *this;}
RandIt operator--(int) {return RandIt{i--};}
RandIt& operator+=(int k) {i += k; return *this;}
RandIt& operator-=(int k) {i -= k; return *this;}
RandIt operator+ (int k) const {return RandIt{i+k};}
RandIt operator- (int k) const {return RandIt{i-k};}
friend RandIt operator+(int k, RandIt a) {return RandIt{k + a.i};}
friend int operator- (RandIt a, RandIt b) {return a.i - b.i;}
friend bool operator==(RandIt a, RandIt b) {return a.i == b.i;}
friend bool operator!=(RandIt a, RandIt b) {return a.i != b.i;}
friend bool operator<=(RandIt a, RandIt b) {return a.i <= b.i;}
friend bool operator< (RandIt a, RandIt b) {return a.i < b.i;}
friend bool operator>=(RandIt a, RandIt b) {return a.i >= b.i;}
friend bool operator> (RandIt a, RandIt b) {return a.i > b.i;}
};
template <int min, int max>
std::knuth_b RandIt<min, max>::rng{std::random_device{}()};
// On some platforms (mingw), random_device is deterministic, so rng
// will always produce the same values.
template <int min, int max>
std::uniform_int_distribution<int> RandIt<min, max>::idist{min, max};