I have a vector-like class that contains an array of objects of type "T"
, and I want to implement 4 arithmetic operators, which will apply the operation on each item:
// Constructors and other functions are omitted for brevity.
template<class T, unsigned int D>
class Vector {
public:
// Add a value to each item: naive implementation.
void operator += (const T&) {
for (int i = 0; i < D; ++i) {
data[i] += value;
}
}
void operator -= (const T&) { ... }
void operator *= (const T&) { ... }
void operator /= (const T&) { ... }
private:
T items[D];
};
Because operators will contain the same boilerplate code (looping over every element and applying appropriate operation), I thought I could generalize it:
template<class T, unsigned int D>
class Vector {
public:
void operator += (const T& value) { do_for_each(???, value); }
void operator -= (const T& value) { do_for_each(???, value); }
void operator *= (const T& value) { do_for_each(???, value); }
void operator /= (const T& value) { do_for_each(???, value); }
private:
void
do_for_each(std::binary_function<void, T, T>& op, T value) {
std::for_each(data, data + D, std::bind2nd(op, value));
}
T data[D];
};
Now, the problem is, how do I pass an operator that takes two intrinsic types and returns void
to do_for_each
, as depicted in the example above? C++ does not let me do this trick for intrinsic types ("T::operator+="
will not work if "T"
is "int"
).
First, you should really return a reference from your operator+=, since you can later use them to implement operator+, operator- and so on. I will change that accordingly.
Also, your do_for_each has to be a template, since it has to know the precise type of the function object, as binary function objects are not polymorph classes. For the actual operation, you want to use std::transform
:
template<class T, unsigned int D>
class Vector {
public:
Vector& operator += (const T& value) {
do_for_each(std::plus<T>(), value);
return *this;
}
Vector& operator -= (const T& value) {
do_for_each(std::minus<T>(), value);
return *this;
}
Vector& operator *= (const T& value) {
do_for_each(std::multiplies<T>(), value);
return *this;
}
Vector& operator /= (const T& value) {
do_for_each(std::divides<T>(), value);
return *this;
}
private:
template<typename BinFun>
void do_for_each(BinFun op, const T& value) {
std::transform(data, data + D, data, std::bind2nd(op, value));
}
T data[D];
};
std::transform will just pass each element to the function object, and assigns the result back to the iterator given as the third argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With