A while back, I asked a question about implementing an idiomatic iterator in C++. I've recently revisited the code, and I'm bothered by the duplication in the begin and end iterators. The code goes over a collection/iterator over a domain, and lazily produces the range using the iterator. After trimming down some code from the accepted answer, here's what I have:
class LinearFunction
{
public:
LinearFunction(double m, double b) : m_(m), b_(b) { }
double operator()(double x) const { return m_ * x + b_; }
private:
double m_, b_;
};
template <typename IterType>
class LinearFunctionIterator
{
public:
LinearFunctionIterator(IterType iter, LinearFunction const &linearFunction)
: xIter_(iter), linearFunction_(linearFunction) { }
LinearFunctionIterator &operator++() {
++xIter_;
return *this;
}
double operator*() const {
return linearFunction_(*xIter_);
}
bool operator!=(LinearFunctionIterator const &other) const {
return xIter_ != other.xIter_;
}
private:
IterType xIter_;
LinearFunction linearFunction_; // <--- (1)
};
template <typename IterType>
class LinearFunctionIteratorProxy
{
public:
LinearFunctionIteratorProxy(IterType xBegin, IterType xEnd,
LinearFunction const &linearFunction)
: xBegin_(xBegin), xEnd_(xEnd), linearFunction_(linearFunction) { }
LinearFunctionIterator<IterType> begin() const {
return { xBegin_, linearFunction_ };
}
LinearFunctionIterator<IterType> end() const {
return { xEnd_, linearFunction_ };
}
private:
IterType xBegin_, xEnd_;
LinearFunction linearFunction_;
};
template<typename Container>
auto makeLinearFunction(Container const &domain,
LinearFunction const &linearFunction)
-> LinearFunctionIteratorProxy<decltype(std::begin(domain))>
{
return { std::begin(domain), std::end(domain), linearFunction };
}
Usage:
#include "LinearFunction.h"
#include <iostream>
#include <vector>
int main()
{
std::vector<double> domain { 1.0, 5.0, 2.0, 8.0 };
LinearFunction linearFunction(10.0, 5.0);
std::cout << "Range:\n";
for(auto rangeValue : makeLinearFunction(domain, linearFunction))
{
std::cout << rangeValue << ", ";
}
}
What I'm looking for from the review:
- Notice in the example usage, that there are three copies of the
LinearFunction
instance: one in the proxy, one in thebegin
iterator, and one in theend
. Is there a better way to achieve the same behavior without this duplication? - General advice to improve this code would be appreciated.