template< typename T >
double GetAverage(T tArray[], int nElements)
{
T tSum = T(); // tSum = 0
for (int nIndex = 0; nIndex < nElements; ++nIndex)
{
tSum += tArray[nIndex];
}
// convert T to double
return double(tSum) / nElements;
};
template <typename T>
class pair {
public:
T a;
T b;
pair () {
a=T(0);
b=T(0);
} ;
pair (T a1, T b1) {
a=a1;
b=b1;
};
pair operator += (pair other_pair) {
return pair(a+other_pair.a, b+other_pair.b);
}
operator double() {
return double(a)+ double(b);
}
};
int main(void)
{
pair<int > p1[1];
p1[0]=pair<int >(3,4);
std::cout<< GetAverage <pair <int >>(p1,1) <<"\n";
}
I can't understand why it prints 0 instead of 3.5.
When I copy code from C++ -- How to overload operator+=? all went fine. But I can't understand where I have made
a mistake
pair operator += (pair other_pair) {
return pair(a+other_pair.a, b+other_pair.b);
}
should be
pair &operator += (const pair &other_pair) {
a += other_pair.a;
b += other_pair.b;
return *this;
}
You need to modify the members of this and return a reference to *this, instead of a new object.
It is also a good idea to pass other_pair as a const reference instead of by value.
Related
I wrote an expression template to sum up to three vectors together. However, as you can see in my code, this doesn't scale very well because for every additional sum operand I have to add another nested template expression. Is there a way to refactor this code to handle a (theoretically) infinite amount of additions?
template<class A>
struct Expr {
operator const A&() const {
return *static_cast<const A*>(this);
}
};
template<class A, class B>
class Add : public Expr<Add<A,B>> {
private:
const A &a_;
const B &b_;
public:
Add(const A &a, const B &b) : a_(a), b_(b) { }
double operator[] (int i) const {
return a_[i] + b_[i];
}
};
class Vector : public Expr<Vector> {
private:
double *data_;
int n_;
public:
Vector(int n, double w = 0.0) : n_(n) {
data_ = new double[n];
for(int i = 0; i < n; ++i) {
data_[i] = w;
}
}
double operator[] (int i) const {
return data_[i];
}
friend Expr<Add<Vector, Vector>> operator+(Vector &a, Vector &b) {
return Add<Vector, Vector>(a, b);
}
friend Expr<Add<Add<Vector, Vector>, Vector>> operator+(const Add<Vector, Vector> &add, const Vector &b) {
return Add<Add<Vector, Vector>, Vector>(add, b);
}
template<class A>
void operator= (const Expr<A> &a) {
const A &a_(a);
for(int i = 0; i < n_; ++i) {
data_[i] = a_[i];
}
}
};
int main() {
constexpr int size = 5;
Vector a(size, 1.0), b(size, 2.0), c(size);
c = a + b + a;
return 0;
}
This was working for me:
class Vector : public Expr<Vector> {
private:
double *data_;
int n_;
public:
Vector(int n, double w = 0.0) : n_(n) {
data_ = new double[n];
for(int i = 0; i < n; ++i) {
data_[i] = w;
}
}
double operator[] (int i) const {
return data_[i];
}
template<class A, class B>
friend Add<A, B> operator+(const Expr<A> &a, const Expr<B> &b) {
return Add<A, B>(a, b);
}
template<class A>
void operator= (const Expr<A> &a) {
const A &a_(a);
for(int i = 0; i < n_; ++i) {
data_[i] = a_[i];
}
}
};
I'm no template wizard (and I'm not up-to-date with the latest possibilities), but you can at least make a function that added a variadic amount of vectors, using something like described in the code below.
You could then buildup you expressiontree like you did before and call this function in you evaluation (operator=) function.
edit: updated the code, based on this solution (credits there)
#include <vector>
#include <algorithm>
template<typename T>
using Vec = std::vector<T>;
template<typename T, typename...Args>
auto AddVector_impl(Vec<Args> const & ... vecs){
auto its = std::tuple(cbegin(vecs)...);
auto add_inc = [](auto&... iters){
return ((*iters++) + ... );
};
auto end_check = [&](auto&...iters){
return ((iters != cend(vecs)) && ...);
};
Vec<T> res;
for(auto it = back_inserter(res); apply(end_check,its);){
*it++ = apply(add_inc,its);
}
return res;
}
template<typename T, typename... Args>
Vec<T> AddVector(Vec<T> const& vt, Vec<Args> const&... vargs){
return AddVector_impl<T>(vt,vargs...);
}
#include <iostream>
int main() {
constexpr auto size = 5;
Vec<double> a(size, 1.0), b(size, 2.0);
auto c = AddVector(a, b, a);
for(auto const& el : c){
std::cout << el << " ";
}
}
outputs:
4 4 4 4 4
I need a function to add values to v[i] using the operator+
the vector v contains the values 10,2 and 3.
#include <iostream>
#include <vector>
template<typename T>
class Measurement
{
private:
T val;
public:
Measurement(T a)
: val{ a }
{}
T value() const { return val; }
Measurement<T>& operator+(const T& nr)
{
//... ???
return *this;
}
};
int main()
{
//create a vector with values (10,2,3)
std::vector<Measurement<int>> v{ 10,2,3 };
v[2] + 3 + 2; //add at v[2] value 5
for (const auto& m : v) std::cout << m.value() << ",";
return 0;
}
The result must be 10,2,8
Just add the val of the instance to other nr
Measurement<T>& operator+(const T& nr)
{
this->val += nr;
return *this;
}
However, overloading the operator+ for this might be misleading and should be avoiding such. Therefore I would suggest the traditional way
Measurement<T> operator+(const T& nr)
{
Measurement<T> tmp{ *this };
tmp.val += nr;
return tmp; // returns the temporary, which you need to reassign!
}
and do
v[2] = v[2] + 3 + 2;
for the required result.
Or even better provide operator+= which meant does return the reference to the Measurement<T>
Measurement<T>& operator+=(const T& nr)
{
this->val += nr;
return *this;
}
and call it like
v[2] += 3 + 2;
I have the following overloaded functions:
float myFunc(Vector2D vec) {
Temp2D temp;
for (int i = 0; i < 10; i++) {
temp += computeTemp(vec, i);
}
return temp.compute_a_float();
}
float myFunc(Vector3D vec) {
Temp3D temp;
for (int i = 0; i < 10; i++) {
temp += computeTemp(vec, i);
}
return temp.compute_a_float();
}
float myFunc(Vector4D vec) {
Temp4D temp;
for (int i = 0; i < 10; i++) {
temp += computeTemp(vec, i);
}
return temp.compute_a_float();
}
where computeTemp is also overloaded for Vector2D, Vector3D, Vector4D:
Temp2D computeTemp(Vector2D, int);
Temp3D computeTemp(Vector3D, int);
Temp4D computeTemp(Vector4D, int);
To avoid code duplication, I have come up with the idea to add a layer of abstraction:
template<typename T0, typename T1>
float myFunc(T0 vec) {
T1 temp;
for (int i = 0; i < 10; i++) {
temp += computeTemp(vec, i);
}
return temp.compute_a_float();
}
float myFunc(Vector2D vec) {
return myFunc<Vector2D, Temp2D>(vec);
}
float myFunc(Vector3D vec) {
return myFunc<Vector3D, Temp3D>(vec);
}
float myFunc(Vector4D vec) {
return myFunc<Vector4D, Temp4D>(vec);
}
However, I want to know if it is possible to avoid an additional layer of abstraction and directly decide the type of variable temp in myFunc.
directly decide the type of variable temp in myFunc.
You can use decltype to determine the type, e.g.
template<typename T0>
float myFunc(T0 vec) {
decltype(computeTemp(vec, 0)) temp;
for (int i = 0; i < 10; i++) {
temp += computeTemp(vec, i);
}
return temp.compute_a_float();
}
BTW,
1. Note that if computeTemp returns by reference instead of return-by-value, the result type of decltype would also be reference (to lvalue or rvalue, depending on how computeTemp returns); you might need to use std::remove_reference with decltype to get the type you want.
2. The expression used for decltype belongs to unevaluated expressions:
The operands of the four operators typeid, sizeof, noexcept, and decltype (since C++11) are expressions that are not evaluated (unless they are polymorphic glvalues and are the operands of typeid), since these operators only query the compile-time properties of their operands. Thus, std::size_t n = sizeof(std::cout << 42); does not perform console output.
Or using auto instead of decltype()
template <typename VT>
float myFunc(VT vec) {
auto temp = computeTemp(vec, 0);
for (int i = 1; i < 10; i++) {
temp += computeTemp(vec, i);
}
return temp.compute_a_float();
}
This starting from C++11 (same limit for decltype()).
For C++98, the best I can imagine is the creation of a custom type traits to select the temp type.
Something like [caution: code not tested]
template <typename>
struct tempType;
template <> struct tempType<Vector2D> { typedef Temp2D type; };
template <> struct tempType<Vector3D> { typedef Temp3D type; };
template <> struct tempType<Vector4D> { typedef Temp4D type; };
template <typename VT>
float myFunc(VT vec) {
typename tempType<VT>::type temp;
for (int i = 0; i < 10; i++) {
temp += computeTemp(vec, i);
}
return temp.compute_a_float();
}
I am trying to develop smart iterator, but even when I create a naive one it crash when I am using sort with it.
The range for loop worked well, but std::sort does not.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<typename I>
class it {
public:
it(I i) : i(i){}
using iterator_category = std::random_access_iterator_tag;
using value_type = typename I::value_type;
using difference_type = std::ptrdiff_t;
using pointer = typename I::pointer;
using reference = typename I::reference;
value_type &operator*() {
return *i;
}
it &operator++() {
++i;
return *this;
}
it &operator--() {
--i;
return *this;
}
bool operator!=(it a) {
return a.i != i;
}
it &operator+(std::size_t n) {
i += n;
return *this;
}
it &operator-(std::size_t n) {
i -= n;
return *this;
}
std::ptrdiff_t operator-(it a) {
return i - a.i;
}
bool operator==(it a) {
return a.i == i;
}
bool operator<(it a) {
return i < a.i;
}
private:
I i;
};
int main()
{
std::vector<int> v = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
for(auto e : v)
std::cout << e << " ";
std::cout << std::endl;
std::sort(it<decltype(v.begin())>(v.begin()), it<decltype(v.end())>(v.end()));
for(auto e : v)
std::cout << e << " ";
std::cout << std::endl;
return 0;
}
The crash happen in "clang-code" here (gdb tell me that) :
struct _Iter_less_iter
{
template<typename _Iterator1, typename _Iterator2>
_GLIBCXX14_CONSTEXPR
bool
operator()(_Iterator1 __it1, _Iterator2 __it2) const
{ return *__it1 < *__it2; }
};
It happened when it deferrence it.
Do you have an idea?
Don't know for sure what the underlying problem is, but this is definitely wrong:
it &operator+(std::size_t n) {
i += n;
return *this;
}
That operator should return a new iterator, and not modify the one it's called on. Something like this:
it operator+(std::size_t n) {
it temp = *this;
temp.i += n;
return temp;
}
Note that this returns the iterator by value, not by reference.
Same thing for operator-.
Your operator+ has the semantics of operator+=, and your operator- has the semantics of operator-=. They should not modify the iterator, but instead create a new iterator with the modified value and return that. Also, they should both accept signed values. In fact, a proper random access iterator should have both sets of operators, so just keep the functions as they are, but change the signatures.
it& operator+=(difference_type n) {
i += n;
return *this;
}
it &operator-=(difference_type n) {
i -= n;
return *this;
}
Then you can implement operator+ and operator- in terms of those. (note that these return by value, not reference, and are marked const)
it operator+(difference_type n) const {
it result = *this;
result += n;
return result;
}
it operator-(difference_type n) const {
it result = *this;
result -= n;
return result;
}
How can I overload so as to make ob2[0][0] << 112.6 work? Currently I am using insert function for this operation.
template <class X>
class A
{
void insert(int row, int col, type val)
{
...
}
};
template <class Y>
class B
{
vector<int> row;
vector<vector<pair<int, Y> > > colval;
}
int main()
{
B<float> ob1;
A<B<float> > ob2;
ob2[0][0] << 112.6;
}
Use a proxy object:
class A
{
// provide operator << for a single row/column
struct cell_proxy
{
void operator<<(float value) const
{
target->insert(row, col, value);
}
A* target;
size_t row;
size_t col;
};
// provide access to elements of a single row
struct row_proxy
{
cell_proxy operator[](size_t col)
{
cell_proxy res = {target, row, col};
return res;
}
A* target;
size_t row;
};
row_proxy operator[](size_t row)
{
row_proxy res = {this, row};
return res;
}
};
That said, you can use operator overloading, proxies and templates to you delight, but you can also make code unreadeble and undebuggable. I personally find the insert() call much more readable.
Try this:
template < class E >
class B
{
vector < std::pair < int, E > inner;
public:
E& operator[] ( int i )
{
// resize inner if i is beyond current size
return ( inner [ i ].second );
}
};
template < E >
class A
{
vector < B < E > > outer;
public:
B < E >& operator[] ( int i )
{
// resize outer if i beyond current size
return ( outer [ i ] );
}
};
int main()
{
A < int > a;
a [ 2 ] [ 3 ] = 1;
return ( 0 );
}
It's a little rough around the edges, but...