I was implementing an iterator that takes another float values producing input iterator and returns true if a rising was detected. So, the iterator works effectively as a Software-ADC (Analog-Digital-Converter).
I've minimized the actual code to the following:
#include <iterator>
template<typename It>
struct ADCFilter
{
using iterator_tag = std::input_iterator_tag;
ADCFilter(const float threshold, It it)
: It_{it}, Threshold_{threshold}, LastAnalogVal_{0}
{}
bool operator*()
{
float analog_val = *It_;
// rising edge
if (analog_val >= Threshold_ && LastAnalogVal_< Threshold_)
{
LastAnalogVal_ = analog_val;
return true;
}
// no rising edge
LastAnalogVal_ = analog_val;
return false;
}
ADCFilter operator++() { ++It_; return *this; }
// Problem is here
ADCFilter operator++(int) {auto self = *this; operator++(); return self; }
private:
It It_;
float Threshold_;
float LastAnalogVal_;
};
As you can see I need to cache the last analog value.
And if somebody uses the iterator in such a way:
std::vector<float> v = {...};
auto f = ADCFilter(0.2f, v.begin());
while(true) {
std::cout << *f++; // <- post inc
}
The cached value is never stored as it's only present in the returned copy.
This problem doesn't occur though with pre increment because we are dereferencing the actual iterator and not a copy of it.
I could easily prohibit the usage of post increment operator by not implementing it, but according to https://en.cppreference.com/w/cpp/named_req/InputIterator it must be implemented for input iterators.
So, the question is how can I correctly implement a stateful input iterator that acts like a filter/mapper to another input iterator?
This can be done by reimplementing the operator so that its internal data holds just the bool value, instead of the floating point value from which the bool value is derived only when the iterator gets dereferenced.
In other words, the dereferencing iterator should simply be:
bool operator*() const // It should be const, by the way
{
return value;
}
// ...
private:
bool value;
The constructor initializes the value to false. All the code that's currently in the dereferencing operator gets basically moved into the operator++(), and its end result is an updated value. It is not necessary to hold a copy of the real value getting iterated over, the operator++ can simply compare the current value referenced by the wrapped iterator with the new value after the wrapped iterator gets incremented, and update the value.
The post-increment ++ operator remains unchanged.
Related
#pragma once
#include <memory>
#include <vector>
#include <random>
#include <list>
class City;
class MemberReport;
class CityReport
{
private:
City* mCity;
protected:
static const int BinSize = 7;
class ReportsBin {
public:
std::shared_ptr<MemberReport> mReports[BinSize+1];
bool IsFull();
void Add(std::shared_ptr<MemberReport> report);
};
std::list<std::shared_ptr<ReportsBin>> mReportBins;
public:
explicit CityReport(City* city);
void Add(std::shared_ptr<MemberReport> report);
class Iter
{
public:
Iter(CityReport *cityReport, int pos1, int pos2) : mCityReport(cityReport), mPos1(pos1), mPos2(pos2) {}
bool operator!=(const Iter &other) const
{
return mPos1 != other.mPos1 || mPos2 != other.mPos2;
}
std::shared_ptr<MemberReport> operator *() const { return mCityReport->mReportBins[mPos1][mPos2]; }
const Iter& operator++()
{
mPos1++;
mPos2++;
return *this;
}
private:
CityReport *mCityReport;
int mPos1;
int mPos2;
};
Iter begin() { return Iter(this, 0, 0); }
Iter end() { return Iter(this, 0, 0); }
};
So I'm trying to create a custom iterator class for the class above however, I'm having trouble with the operator* and the operator++ due to the return type being stored in the form of a singly linked list inside of a list of shared pointers.
So I tried having the first parameter of the iterator constructor being ReportsBin* reportsBin although that didn't work since I need to return type std::shared_ptr<MemberReport> in the operator*. Now, I have it as CityReport* cityReport so that I can access the list of shared pointers mReportBins eventually leading to mReports. The problem is when I do mCityReport->mReportBins[mPos1][mPos2] to access mReports, I am not able to do so since you can't access lists using indices. My only other idea is to create an iterator within the operator* to iterate over the list of shared pointers of type std::list<std::shared_ptr<ReportsBin>> but I feel as though that defeats the whole purpose of the iterator class. I can't modify the CityReport class either, I can only work with the iterator class at hand.
I think using int for mPos1 is a mistake.
An iterator would be a better type in most situations. Unfortunately you make mReportBins accessible (as it is protected and not private) so depending on how you use it maybe int is better. But for argument’s sake; let's use an iterator.
While we are at it may as well use an iterator for mPos2 as it will make the logic easier (though you can use int and swap checks for end against checks against the size of the array without any major difference.
Let's address the ReportsBin type first:
class ReportsBin {
public:
// Rather than using a C-Array
// Upgrade to a std::array this makes it easier using some types.
using ReportsCont = std::array<std::shared_ptr<MemberReport>, BinSize+1>;
// We may not be upgrading this to full container status.
// But lets make accessing the members container here easier by
// providing some simple iterator accesses to the memebers.
using iterator = ReportsCont::iterator;
ReportsCont mReports;
iterator begin() {return std::begin(mReports);}
iterator end() {return std::end(mReports);}
bool IsFull();
void Add(std::shared_ptr<MemberReport> report);
};
Next lets address the container you are using to store the ReportBin. You use a std::list and I am fine with theat. But lets make accessing the type information easier by using a couple of using directives.
using Container = std::list<std::shared_ptr<ReportsBin>>;
using ContainerIter = Container::iterator;
Container mReportBins;
Now we can define the member of Iter in terms of the types we have defined that makes it easy to read and easy to modify in a single place.
class Iter // More traditionally this should be iterator
{
// STUFF
..
private:
CityReport* mCityReport;
ContainerIter mPos1;
ReportsBin::iterator mPos2;
};
This makes our dereference operator trivial.
std::shared_ptr<MemberReport> operator*() const
{
return *mPos2;
}
Constructor:
You only ever used the constructor to the first element. So why force this user to provide those 0,0. Let's remove that. Let's also not pass around raw pointers unless we really have to, so make the parameter a CityReport& so that users know it can never be null it always refers to something.
Iter(CityReport& cityReport, ContainerIter p1)
: mCityReport(&cityReport) // convert to pointer here
// Allows copying.
, mPos1(p1)
{
// We can only set mPos2 if mPos1 is dereferancable.
if (mPos1 != mCityReport->mReportBins.end()) {
mPos2 = (*mPos1)->mReports.begin();
}
}
Like the constructor, you need to take special care of the test for situations where mPos1 is no longer dereference as mPos2 is no longer valid in a test. So the comparison becomes a little more complex:
bool operator==(const Iter &other) const
{
auto end = mCityReport->mReportBins.end();
// If mPos1 and other.mPos1 are both at the end.
// then the value of mPos2 have no meaning, so don't compare.
return (mPos1 == end && other.mPos1 == end)
// Otherwise, make sure both iterators are the same.
|| (mPos1 == other.mPos1 && mPos2 == other.mPos2);
}
// Usually good to define both == and != and define them in
// terms of each other for consistency.
bool operator!=(const Iter &other) const {return !(*this == other);}
This leaves the increment:
Your increment looks strange. If you want to move diagonally across the array that seems fine. But you don't make a check to make sure the two containers are square with each other. So it looks wrong. So I have taken the liberty of redefining the increment so it goes across all elements.
const Iter& operator++()
{
// Increment mPos2 to the next element.
// Note this is fine without a test.
// It is illegal to call operator++ on an iterator where
// mPos1 is at the end.
++mPos2;
// If we reach the end of its container
// Then we need to do some extra work to move to the next
// container.
if (mPos2 == (*mPos1)->mReports.end()) {
// Increment the outer iterator.
// If we are not at the end of the container
// reset mPos2
++mPos1;
if (mPos1 != mCityReport->mReportBins.end()) {
mPos2 = (*mPos1)->mReports.begin();
}
}
return *this;
}
Now lets define begin and end.
Iter begin() { return Iter(*this, this->mReportBins.begin()); }
Iter end() { return Iter(*this, this->mReportBins.end()); }
Lets address other things you should be thinking about.
You look like you want to make this a container.
To do that you need to define a few more helper types in the container type and support a couple of other standard functions.
There are a couple of different types of container:
https://en.cppreference.com/w/cpp/container
But the basics of what you "should" support are here:
https://en.cppreference.com/w/cpp/named_req/Container
Types your container should support:
// A typical container class will define these.
using value_type = T;
using reference = T&;
using const_reference = const T&;
using iterator = <Type of Your Iterator>;
using const_iterator = const iterator;
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
// Note: You may have to customize these.
// Or explicitly not support them if that makes sense.
Your Iterator class should also define some (very similar types) types:
https://en.cppreference.com/w/cpp/iterator/iterator_traits
You can define an explicit instantiation of iterator_traits to get these types. But it is usually easier to define them in the iterator type itself.
using value_type = MemberReport;
using reference = MemberReport&;
using const_reference = const MemberReport&;
using iterator = MemberReport*;
using const_iterator = MemberReport const*;
using difference_type = std::ptrdiff_t;
using size_type = std::size_t;
I have a task where I have to count how many of different kinds of objects there are and save the result to later create graphs out of them. What I am doing is creating sorted vectors holding elements that satisfy different conditions, and calling std::set_intersection on them to find how many of them satisfy a composite statement. For example:
// Count round and black objects
std::vector<SomeObject*> roundAndBlackObjects;
std::set_intersection(roundObjects.begin(), roundObjects.end(),
blackObjects.begin(), blackObjects.end(),
std::back_inserter(roundAndBlackObjects));
std::size_t numRoundAndBlackObjects = roundAndBlackObjects.size();
This seems to be too complex though. I only wanted to count the common elements after all. Is there a way to omit the unnecessary vector push_backs? Is there an easy way to do this? Something like an output iterator generator, that creates a dummy output iterator that does not construct anything, just counts the calls to its increments. That way I could do something like this:
// Count round and black objects
std::size_t numRoundAndBlackObjects = 0;
std::set_intersection(roundObjects.begin(), roundObjects.end(),
blackObjects.begin(), blackObjects.end(),
std::iterator_callback_counter<SomeObject*>(numRoundAndBlackObjects));
If there is no such thing, is there an easy way to create such a meta-object?
You could almost use a plain int.
std::set_intersection calls two operators on the output iterator, unary operator* and operator++. Calling the latter on int is how you count, but you need a wrapper to ignore operator*.
How do you ignore operator*? It must return something which allows *iter = value. Well, your wrapper could return *this. That just means operator= also gets called on your wrapper. That again can just return *this.
So, to put it all together :
class counter {
size_t count = 0; // Let's count a bit further
public:
counter& operator++() { ++count; return *this; } // ++X
counter& operator++(int) { ++count; return *this; } // X++
counter& operator*() { return *this; }
template<typename T> counter& operator=(T&&) { return *this; }
counter& operator=(counter&) = default; // Don't break normal assignment.
operator size_t() const { return count; }
};
I just read a chapter on templates and iterators but this still is hard to understand. basically i want to create a Set template class that accepts only one of each type of object that you put into it, implemented using a vector.
Problem is, I don't know how to write the insert function in the Set class, and the constructor in the nested iterator class. Also, most of the functions I have provided are examples from the chapter in the text, I do not even know if they are necessary or I am doing it right. Comments? Because this is a very confusing one. Here is my code:
//testSetClass.cpp
#include <iostream>
#include <vector>
using namespace std;
/****************************CLASS DEFINITION*********************************/
// -----------------------------------------
// SET
// -----------------------------------------
template <class T>
class Set
{
vector<T> theSet;
public:
Set() {}
Set(const Set& s): theSet(s.theSet){} //copy constructor
~Set(){ theSet.clear(); }
void insert(T t)
{
//insert in orderly fashion? as set class does too
//also, how do i check for duplicates?
theSet.push_back(t);
}
//nested iterator class: that supports the begin() and end() sentinel
class iterator; //declaration
friend class iterator;
class iterator //definition
{
Set<T>& s;
int index;
public:
iterator(const Set<T>& ss): s(ss), index(0){}
//to create the "end sentinel" operator:
iterator(Set<T>& ss,bool):s(ss){} //???
T operator*() {return s.theSet.at(index);} //is this right?
T operator++() //prefix form
{
return ++s.theSet.at(index);
}
T operator++(int) //postfix form
{
return s.theSet.at(index)++;
}
bool operator!=(const iterator& ri)const {return index!=ri.index;}
};
//iterators begin() and end()
iterator begin()const { return iterator (*this); }
//create the end sentinel:
iterator end() { return iterator (*this,true); } //why?
};
/*************************************END OF CLASS DEFINITIONS*********************************/
/* *****************************************************************************
* MAIN
* *****************************************************************************
*
* REMARKS:
* to test that the class works correctly.
* *****************************************************************************/
int main (int argv, char const *argc[])
{
Set<int> other;
for(int i = 0; i<10; ++i)
other.insert(i);
for(Set<int>::iterator start = other.begin(); start != other.end(); start++)
cout<<*start<<endl;
cout << "\n\nProgram ends successfully!" <<endl;
}
Use std::vector<T>::iterator for your iterator. And similar for your const_iterator.
To find, use std::equal_range. If first==second, return end().
To insert, find. If it is already there, stop. If it isn't there, insert it. The lazy way to insert it is to push back, then sort. Do it the lazy way first.
Once you have done the above, you have a working Set<T>. Test it against std::set<T> with a bunch of data. Write a bunch of unit tests to make sure this Set<T> works just like std::set<T> with regards to duplicates, ordering, finding, etc.
Now make your Set<T> more efficient. Replace that Find with a call to lower_bound and <, and insert the element where it is supposed to be instead of insert-then-sort. (It is ok that this makes no sense to you; get a working Set before even reading this, then spend some time unpacking it).
Or, make a lazy-sort Set<T> that appends blindly, and only sorts exponentially rarely on insert. On read, it either sorts, or it examines the sorted part with a binary search and the remaining (small) part with a linear search. Or somesuch.
Another improvement would be to write a manual iterator like above; one that isn't invalidated as easily as a std::vector iterator. This is ... tricky to get right.
But work on efficiency after you have correctness.
//also, how do i check for duplicates?
With theSet.find()....
iterator(Set& ss,bool):s(ss){} //???
That's not going to work. Many options, easiest being to also set index to s.theSet.size() so the existing != will work.
T operator*() {return s.theSet.at(index);} //is this right?
Nope... you need to return a T& to - rather than a copy of - the vector's element.
operator++ / operator++(int)
You need to increment the iterator (i.e. index), not increment what the iterator addresses, and should return *this (with return type iterator&). Study some iterator implementations....
iterator end() { return iterator (*this,true); } //why?
Why what? Anyway, you'd ideally provide const versions of begin() and end() that return const_iterators (which would be pretty much like iterator but only expose const T&), as well as non-const versions returning iterators: you're mixing these two ideas, with iterator begin() const.
I have below code:
#include<iostream>
#include <vector>
using namespace std;
template<class T>
class Stack
{
private:
vector<T> stack;
public:
T Pop()
{
if (stack.size()!=0)
{
T temp;
temp=stack[stack.size()-1];
stack.erase(stack.begin()+stack.size()-1);
return temp;
}
else
//return nothing
^^^^^^^^^^^^^^^^
//How i can do above by code
}
In pop function: I want if stack.size==0; Pop function return nothing
How I can do it?
This is basically a question of how to handle non-total functions—functions that are not necessarily defined for all possible inputs. There are many ways to go about it, though none of them is type-safe:
Have two separate functions for retrieving and erasing the top element of the stack, much like std::stack::top() and std::stack::pop().
Use a reference parameter and return a bool indicating whether an element was returned:
bool pop(T& value) {
if (stack.empty())
return false;
value = stack.back();
stack.pop_back();
return true;
}
The caller can write:
T value;
if (stack.pop(value)) {
use(value);
}
Return a boost::optional<T>.
Return a default-constructed T instance. This requires that T be default-constructible, which is already imposed by some std::vector member functions.
Throw an exception, documenting that a precondition was violated.
Leave the behaviour of popping an empty stack undefined.
I recommend #1, #2, or #3, depending on preference and what fits best with the surrounding code.
You probably still want to do the same way as std::stack that to split into std::stack::top and std::stack::pop. You don't want to pop to return a value.
Here is the explaination from http://cpptruths.blogspot.com.au/2005/10/why-does-stdstackpop-returns-void.html
http://www.sgi.com/tech/stl/stack.html explains
[3] One might wonder why pop() returns void, instead of value_type. That is, why must one use top() and pop() to examine and remove the top element, instead of combining the two in a single member function? In fact, there is a good reason for this design. If pop() returned the top element, it would have to return by value rather than by reference: return by reference would create a dangling pointer. Return by value, however, is inefficient: it involves at least one redundant copy constructor call. Since it is impossible for pop() to return a value in such a way as to be both efficient and correct, it is more sensible for it to return no value at all and to require clients to use top() to inspect the value at the top of the stack.
std::stack < T > is a template. If pop() returned the top element, it would have to return by value rather than by reference as per the of above explanation. That means, at the caller side it must be copied in an another T type of object. That involves a copy constructor or copy assignment operator call. What if this type T is sophisticated enough and it throws an exception during copy construction or copy assignment? In that case, the rvalue, i.e. the stack top (returned by value) is simply lost and there is no other way to retrieve it from the stack as the stack's pop operation is successfully completed!
The practice way is to use pop(), top(), empty() together:
T top()
{
return stack[size()-1];
}
void pop()
{
stack.erase(stack.begin()+stack.size()-1);
}
usage:
if (!stack.empty())
{
T t = top();
pop();
}
There are a couple of alternatives. One is to return an instance of T constructed with the standard constructor:
return T();
Another way would be to return a special sentinel wrapper object, that can be implicitly converted to T, and have a comparison operator so the user can check it.
Here's one way of doing this. The idea is to package a Boolean flag together with the result in a tuple. The flag indicates whether there is a result or not. Notice though that the current implementation requires T to be default constructible.
template<class T>
class Stack
{
private:
std::vector<T> stack;
public:
typedef std::tuple<bool, T> return_t;
void Push(const T& t)
{
stack.push_back(t);
}
return_t Pop()
{
if (stack.size()!=0)
{
T temp;
temp=stack[stack.size()-1];
stack.erase(stack.begin()+stack.size()-1);
return std::make_tuple(true, temp);
}
else
return std::make_tuple(false, T());
}
};
int main()
{
Stack<int> my_stack;
bool has_result;
int result;
my_stack.Push(5);
std::tie(has_result, result) = my_stack.Pop();
std::cout << "has result = " << has_result << "\n";
std::cout << "result = " << result << "\n";
std::tie(has_result, result) = my_stack.Pop();
std::cout << "has_result = " << has_result << "\n";
}
You can also do something like declare the pop method as void or even better, bool to get the status of the operation and pass the T type as an argument by reference in order to store the result in it:
bool Pop (T& item)
{
if (stack.size() != 0)
{
// your code
item = temp; // you can even use item instead of temp from the begining
return true;
}
return false;
}
I have a class (foo) that contains a vector.
If i try iterating over the elements in the vector like so:
for(vector<random>::iterator it = foo.getVector().begin();
it != foo.getVector().end(); ++it) {
cout << (*it) << endl;
}
The first element is always corrupted and returns garbage data.
However, if do something like:
vector<random> v = foo.getVector();
for(vector<random>::iterator it = v.begin();
it != v.end(); ++it) {
cout << (*it) << endl;
}
Everything appears to be working fine. Is there a "gotcha" that I do not know about?
I've also tried doing cout << foo.getVector()[0] << endl; outside of the loop but that appears to be working ok.
Thanks.
Edit:
Here's my header file:
#ifndef HITS
#define HITS
#include <vector>
#include "wrappers.h"
class Hits {
public:
Hits();
std::vector<word_idx_value> getVector() {return speech_hits;}
const std::vector<word_idx_value> getVector() const {return speech_hits;}
void add(const word_idx_value&);
Hits &operator+=(const Hits&);
private:
std::vector<word_idx_value> speech_hits;
};
#endif
for(vector<random>::iterator it = foo.getVector().begin();
The temporary vector is returned when you do foo.getVector() and it gets destroyed the moment ; is encountered after foo.getVector().begin(); Hence iterator becomes invalid inside the loop.
If you store the value of foo.getVector(); in vector v ( v = foo.getVector();) and then use the vector v, it works fine. It is because the vector v is valid throughout the loop.
getVector() returns a vector by value. The two invocations of getVector (begin() and end()) return different copies of the vector, so you call begin() on one object and end() on another. What you get is two iterators into two different containers. Comparing those two iterators with != yields an undefined value.
getVector() returns vector by value and in the first case you get a temporary variable that gets destroyed once you're inside the loop. In the second case you copy the result into a local variable that is still alive while inside the loop. Possible solution is to return vector by const reference.
You error is in the getVector() method.
Return by reference.
class Hits
{
public:
std::vector<word_idx_value>& getVector() {return speech_hits;}
// ^
// Add the & to return by reference.
// You may also want a const version at some point.
std::vector<word_idx_value> const& getVector() const {return speech_hits;}
If you don;t return by reference you are creating a temporary copy. The copy is then destroyed after it has been used. In this case after the begin() has executed the temporary object is destroyed, and thus the iterator returned by begin() is not valid.
modify the getVector function to return the object reference like this:
std::vector<word_idx_value>& getVector() {return speech_hits;}