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; }
};
Related
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.
I implemented SpareArray class. It's a big one, so there is no sense to show it all, but what is important is that is has insert method, which makes it possible to insert values at any index (from zero to "infinity"). So, my client code may look like so:
auto arr = new SpareArray<int>{};
arr.insert(100, 1);
The above code inserts value 1 at index 100. Now, I want to be able to use square brakets notation to get the same result:
auto arr = new SpareArray<int>{};
arr[100] = 1; //I want this line to internally call arr.insert(100, 1);
So, how can operator[] be difined to internally call insert method? I need this call, because insert method has some business logic and I want this business logic to take place also in this case (in case of []).
You can return a proxy that does the final call to insert and acts as a wrapper around an element of your array.
template<typename T>
struct Proxy {
Proxy(SpareArray<T> &This, std::size_t Index) : This(This), Index(Index) {}
T &operator=(const T &Value) {
This.insert(Index, Value);
return This.get(Index); // or however you get an element
}
operator T&() { return This.get(Index); }
operator const T&() const { return This.get(Index); }
private:
SpareArray<T> &This;
std::size_t Index;
};
For simplicity, I didn't add more but I would expect such a class to have proper noexcept semantics and a move assignment operator, for example. You also might want to make sure that you delete the copy constructors and such.
I'm writing a function that will separate a vector of objects into two vectors depending on the value of one of their objects. I want it then to return whichever of the vectors.
This is the code I have so far
std::vector<AggregatedQuoteType> OrderBook::get_aggregated_order_book(SellBuyType which_side) const
{
std::vector<AggregatedQuoteType> ret;
std::vector<AggregatedQuoteType>::const_iterator i = v_OrderInfo.begin();
for (; i != v_OrderInfo.end(); ++i)
((*i).get_SB_type()==BUY ? v_BuyOrders : v_SellOrders).push_back((*i));
if(which_side==SELL){
ret = v_SellOrders;
}
else{
ret = v_BuyOrders;
}
return ret;
}
EDIT
I'm getting the following error:
[Error] no matching function for call to 'std::vector::push_back(const AggregatedQuoteType&) const'
You have marked your function get_aggregated_order_book as const.
OrderBook::get_aggregated_order_book(SellBuyType which_side) const
^^^^^
Here!
The const keyword in C++ implies that you will not be making changes to any members in your class, which I presume v_BuyOrders and v_SellOrders are.
If you're modifying the members of your OrderBook class, you need to make the method non-const.
Do you need the v_BuyOrders and v_SellOrders populated at all or just return whatever matches which_side? If the latter, how about just applying a copy_if operation and return the result?
std::vector<AggregatedQuoteType> ret;
std::copy_if(v_OrderInfo.cbegin(), v_OrderInfo.cend(), std::back_inserter(ret),
[=](const AggregatedQuoteType &at) { return at.get_SB_type() == which_side) };
return ret;
EDIT: not using lambda/C++11,
struct pred {
SellBuyType type;
pred(SellBuyType t) : type(t) {}
bool operator()(const AggregatedQuoteType &at) {
return at.get_SB_type() != type; // Copies the elements for which this returns false
}
};
std::remove_copy_if(v_OrderInfo.cbegin(), v_OrderInfo.cend(), std::back_inserter(ret), pred(which_side));
Do note however that remove_if/remove_copy_if doesn't actually remove anything, just shifts the "removed" elements to the back of the vector. If you want to remove the elements as well use vector::erase on the return value of remove_copy_if.
I have a question about Operator Overloading in C++.
For an assignment, I have to write a class which encompasses an array, sort of like the ArrayList in Java.
One of the things I have to do is keep track of the size of the array. Size is the amount of elements included, whereas capacity is the maximum amount which CAN be included before the class has to expand the array.
Client code specifies the size when they call the constructor. However, when new elements are added, I have to figure out a way to change the size.
My teacher said something about being able to overload an operator for different sides of an equality. Is this a real thing, or did I misunderstand her? If this works, it would be the optimal solution to my problem.
My current overloading for the [] operator is:
int & ArrayWrapper::operator [] (int position){
if(position == _size){
if(_size == _capacity){
changeCapacity(_capacity+10);
}
}
return _array[position];
}
This works fine for retrieval, but I'd like to have it so that if someone calls it from the left hand side of a '=' then it checks to see if it needs to expand the size or not.
EDIT: If this isn't a real thing, can anyone think of a different solution to the problem? One solution I thought of is to have the getSize() method just go through the entire array every time it is called, but I'd really rather not use that solution because it seems cheesy.
EDIT: For clarification, I'm not asking whether or not my expansion of an array works. I need to add 1 to size every time a new element is added. For example, if the client creates an array of size 15 and capacity 25, and then tries to add something to Array[15], that SHOULD increase the size to 16. I was wondering if there was a way to do that with overloading.
A simple approach, which doesn't quite do what you want, is to overload on whether the array is const or mutable.
This doesn't distinguish between whether the array is being used on the left-hand side of assignment (as a lvalue) or on the right (as a rvalue); just on whether it's allowed to be modified or not.
// Mutable overload (returns a mutable reference)
int & operator[](size_t position) {
if (position >= _size) {
if (position >= _capatity) {
// increase capacity
}
// increase size
}
return _array[position];
}
// Const overload (returns a value or const reference)
int operator[](size_t position) const {
if (position >= _size) {
throw std::out_of_range("Array position out of range");
}
return _array[position];
}
If you really want to tell whether you're being assigned to or not, then you'll have to return a proxy for the reference. This overloads assignment to write to the array, and provides a conversion operator to get the value of the element:
class proxy {
public:
proxy(ArrayWrapper & array, size_t position) :
_array(array), _position(position) {}
operator int() const {
if (_position >= _array._array._size) {
throw std::out_of_range("Array position out of range");
}
return _array._array[_position];
}
proxy & operator=(int value) {
if (_position >= _size) {
if (_position >= _capatity) {
// increase capacity
}
// increase size
}
_array._array[_position] = value;
return *this;
}
private:
ArrayWrapper & _array;
size_t _position;
};
You probably need to declare this a friend of ArrayWrapper; then just return this from operator[]:
proxy ArrayWrapper::operator[](size_t position) {
return proxy(*this, position);
}
This approach is fine. There's an error in the code, though: what happens if someone calls that operator with a position that's equal to the current size of the array plus 100?
The question is whether you really want different behavior depending on
which side of the = you are. Your basic idea will work fine, but will
expand the array regardless of the side you're on, e.g.:
ArrayWrapper a(10);
std::cout << a[20] << std::end;
will result in expanding the array. Most of the time, in such cases,
the preferred behavior would be for the code above to raise an exception,
but for
ArrayWrapper a(10);
a[20] = 3.14159;
to work. This is possible using proxies: first, you define double
ArrayWrapper::get( int index ) const and void ArrayWrapper::set( int
index, double newValue ); the getter will throw an exception if the
index is out of bounds, but the setter will extend the array. Then,
operator[] returns a proxy, along the lines of:
class ArrayWrapper::Proxy
{
ArrayWrapper* myOwner;
int myIndex;
public:
Proxy( ArrayWrapper& owner, int index )
: myOwner( &owner )
, myIndex( index )
{
}
Proxy const& operator=( double newValue ) const
{
myOwner->set( myIndex, newValue );
}
operator double() const
{
return myOwner->get( myIndex );
}
};
In case you're not familiar with the operator double(), it's an
overloaded conversion operator. The way this works is that if the
operator[] is on the left side of an assignment, it will actually be
the proxy which gets assigned to, and the assignment operator of the
proxy forwards to the set() function. Otherwise, the proxy will
implicitly convert to double, and this conversion forwards to the
get() function.
Im trying to overload the [] operator in c++ so that I can assign / get values from my data structure like a dictionary is used in c#:
Array["myString"] = etc.
Is this possible in c++?
I attempted to overload the operator but it doesnt seem to work,
Record& MyDictionary::operator[] (string& _Key)
{
for (int i = 0; i < used; ++i)
{
if (Records[i].Key == _Key)
{
return Records[i];
}
}
}
Thanks.
Your code is on the right track - you've got the right function signature - but your logic is a bit flawed. In particular, suppose that you go through this loop without finding the key you're looking for:
for (int i = 0; i < used; ++i)
{
if (Records[i].Key == _Key)
{
return Records[i];
}
}
If this happens, your function doesn't return a value, which leads to undefined behavior. Since it's returning a reference, this is probably going to cause a nasty crash the second that you try using the reference.
To fix this, you'll need to add some behavior to ensure that you don't fall off of the end of the function. One option would be to add the key to the table, then to return a reference to that new table entry. This is the behavior of the STL std::map class's operator[] function. Another would be to throw an exception saying that the key wasn't there, which does have the drawback of being a bit counterintuitive.
On a totally unrelated note, I should point out that technically speaking, you should not name the parameter to this function _Key. The C++ standard says that any identifier name that starts with two underscores (i.e. __myFunction), or a single underscore followed by a capital letter (as in your _Key example) is reserved by the implementation for whatever purposes they might deem necessary. They could #define the identifier to something nonsensical, or have it map to some compiler intrinsic. This could potentially cause your program to stop compiling if you move from one platform to another. To fix this, either make the K lower-case (_key), or remove the underscore entirely (Key).
Hope this helps!
On a related note, one of the problems with operator[](const Key& key) is that, as templatetypedef states, in order to return a reference it needs to be non-const.
To have a const accessor, you need a method that can return a fail case value. In STL this is done through using find() and the use of iterators and having end() indicate a fail.
An alternative is to return a pointer, with a null indicating a fail. This is probably justified where the default constructed Record is meaningless. This can be also be done with the array operator:
Record* MyDictionary::operator[] (const string& keyToFind) const
{
for (int i = 0; i < used; ++i)
{
if (Records[i].Key == keyToFind)
{
return &Records[i];
}
}
return 0;
}
There is certainly a view that operator[] should return a reference. In that case, you'd most likely implement find() as well and implement operator[] in terms of it.
To implement find() you need to define an iterator type. The convenient type will depend in implementation. For example, if Records[] is a plain old array:
typedef Record* iterator;
typedef const Record* const_iterator;
const_iterator MyDictionary::end()const
{
return Records + used;
}
const_iterator MyDictionary::begin() const
{
return Records;
}
const_iterator MyDictionary::find(const string& keyToFind) const
{
for (iterator it = begin(); it != end(); ++it)
{
if (it->Key == keyToFind)
{
return it;
}
}
return end();
}