unary operator- overload [c++]

Started by
5 comments, last by Ruchir 16 years, 11 months ago
Hi, I'm working on something similar to lambda (boost) library, however on a much smaller lever and am trying to overload unary operator-. This is what the relevant code fragment looks like, class a2 { public: a2() { } int operator()(int& x) { return x; } template <class B> Expr<a2, B> operator=(B b) { Expr<a2, B> expression(*this, b, "="); return expression; } a2 operator+(void) const { return *this; } /*int operator-(void) const { return -(*this); }*/ } _1; Anyone got suggestions? :) Or is this too unclear? I can post my whole code in that case... [edit] I'm writing this fragment to make this work > for_each(v.begin(), v.end(), _1 = - _1); [/edit]
Advertisement
Quote:
Anyone got suggestions? :)

By applying my considerable powers of deduction based upon that code snippet you provided, I can conclude that your problem is that you have not specified an entry point (in other words, where is main()?) :P

Now, obviously, that's not your real problem and it's not really related at all. So yes, more code would be helpful, in particular:
a) Provide the complete code that stimulates the error(s).
b) Provide the error(s) that are stimulated.

Otherwise, it's hard to tell what's wrong, and what you want fixed.

Your commented-out operator- looks highly suspect because *this is not of type int... it's of type a2. So the return type doesn't match; you're also trying to reapply unary operator-, which is bogus. But without seeing the actual errors and a more complete code transcript, I can't say for sure.
Here's my full code from a2.h . My main() contains definition of vector<int> v, and method call for_each(v.begin, v.end(), _1 = -_1);

I've commented operator- in a2 because I can't think of a way around it. Here's my complete code >>

#include <string>
#include <iostream>
#include <ostream>
using namespace std;

//Expr class to evaluate expression
template <class A, class B>
class Expr {

public:
A l_v; // Left Value
B r_v; // Right Value
string Op; // Operator

//Constuctor with no parameters
Expr() { }

Expr(A l, B r, string o) {
l_v = l;
r_v = r;
Op = o;
}

int operator()(int &);
};


//class a2 as a placeholder/expression call for _1
class a2 {

public:
a2() {
}

int operator()(int& x) {
return x;
}

template <class B> Expr<a2, B> operator=(B b) {
Expr<a2, B> expression(*this, b, "=");
return expression;
}

a2 operator+(void) const {
return *this;
}

/*int operator-(void) const {
return ?;
}*/

};

int clarifyExpr(int x, int y) {
return x;
}

int clarifyExpr(a2 a, int x) {
return x;
}

template <class A, class B> int clarifyExpr(Expr<A,B> expression, int x) {
return eval(expression, x);
}

//Evaluation of the given expression
template <class A, class B>
int eval(Expr<A,B> expression, int &x) {
int var;
int l_v;
int r_v;

if(expression.Op != "<<") {
l_v = clarifyExpr(expression.l_v, x);
r_v = clarifyExpr(expression.r_v, x);
if(expression.Op == "+") {
var = l_v + r_v;
} else if(expression.Op == "-") {
var = l_v - r_v;
} else if(expression.Op == "/") {
var = l_v / r_v;
} else if(expression.Op == "*") {
var = l_v * r_v;
} else if(expression.Op == "=") {
x = r_v;
}

}
return var;
}

ostream& clarifyExprForOut(ostream& os, int x) {
return os;
}

template <class A, class B> int Expr<A, B> :: operator()(int &x) {
return eval(*this, x);
}

template <class A, class B> int ExprForOut<A,B> :: operator()(int &x) {
return evalOut(*this, x);
}

template <class A, class B> Expr <A,B> operator+(A a, B b) {
Expr <A, B> expression(a, b, "+");
return expression;
}

template <class A, class B> Expr <A, B> operator-(A a, B b) {
Expr <A, B> expression(a, b, "-");
return expression;
}

template <class A, class B> Expr <A, B> operator*(A a, B b) {
Expr <A, B> expression(a, b, "*");
return expression;
}

template <class A, class B> Expr <A, B> operator/(A a, B b) {
Expr <A, B> expression(a, b, "/");
return expression;
}

//explicit placeholder definition for _1
a2 _1;
Well the problem looks pretty obvious to me. Your unary minus operator is simply calling unary minus operator on itself. Thus you have an infinite loop!
Oh, and the return type should possibly be a2, not int.

I see you're using expression templates. Good luck with that!
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Thanks for the luck.. I haven't made much progress though. I can' t return a2 with a negative value off stack. Thats why I'm completely confused.. In fact I'm looking for any possible suggestions, because I know the lines I'm thinking on is probably completely incorrect.. :(
Quote:In fact I'm looking for any possible suggestions, because I know the lines I'm thinking on is probably completely incorrect.. :(


Ok, its not to bad but there are a number of things which would simplify it lots.

1) Move the operators out of the decleration of a2, this becomes particularly important when you start to do more complicated expressions such as _1 = _2 + 3 * _4, As it stands you would have to write operator overloads for each placeholder (_1, _2, ...) and the result of adding multiplying etc...

2) Maintain some extra type information, currently no longer have acess to the operation at compile time once youve created Expr.

For example:
// note the following is untested and may contain errors // (missing typenames and such)template<typename Op, typename Value>struct unary_op{    Value value;    unary_op(Value value) : value(value) {}    BOOST_TYPEOF(Op::eval(value()) operator()()    {        return Op::eval(value());    }    // the *NULL is valid because the expression is never evaluated    template<typename T0>    BOOST_TYPEOF(Op::eval(value(*static_cast<T0*>(0))) operator()(T0 t0)    {        return Op::eval(value(t0));    }    // more operator() overloads which just pass there arguments to value    // (i.e. value(arg1, ..., argn))};template<typename Op, typename LHS, typename RHS>struct binary_op{    LHS lhs;    RHS rhs;    binary_op(LHS lhs, RHS rhs): lhs(lhs), rhs(rhs) { }    BOOST_TYPEOF(Op::eval(lhs(), rhs())) operator()()    {        return Op::eval(lhs(), rhs());    }    template<typename T0>    BOOST_TYPEOF(Op::eval(lhs(*static_cast<T0*>(0)), rhs(*static_cast<T0*>(0))))     operator()(T0 t0)    {        return Op::eval(lhs(t0), rhs(t0));    }    // more operator() overloads that pass there args to lhs and rhs};struct negate_op{    template<typename T>    static BOOST_TYPEOF(-(*static_cast<T*>(0))) eval(T t)    {        return -t;    }};struct add_op{    template<typename T0, typename T1>    static BOOST_TYPEOF((*static_cast<T0*>(0)) + (*static_cast<T1*>(0)))    eval(T0 t0, T1 t1)    {        return t0 + t1;    }};// you need to provide stuff to convert int, float, etc to // lambda_expression< fundamental_wrapper<int> >, etc// fundamental wrapper should have operator() overloads that just// return the value it was constructed with ignoring all paramaterstemplate<typename T>struct lambda_expression{    T value;    lambda_expression(T value): value(value) { }    BOOST_TYPEOF(value()) operator()()    {        return value();    }    BOOST_TYPEOF(value(*static_cast<T0*>(0))) operator()(T0 t0)    {        return value(t0);    }    // ......};template<typename LHS, typename RHS>lambda_expression<    binary_op    <        add_op,        LHS,        RHS    >>operator+(lambda_expression<LHS> lhs, lambda_expression<RHS> rhs){    return lambda_expression    <        binary_op        <            add_op,            LHS,            RHS        >    >    (        binary_op<add_op, LHS, RHS>(lhs.value, rhs.value)    );}template<typename T>lambda_expression< unary_op<negate_op, T> > operator-(lambda_expression<T> value){    return lambda_expression< unary_op<negate_op, T> >    (unary_op<negate_op, T>(value.value));}struct place_holder_1 : public    lambda_expression<place_holder_1>{    template<typename T0>    T0 operator()(T0 t0)    { return t0; }    template<typename T0, typename T1>    T0 operator()(T0 t0, T1 t1)    { return t0; }    // ........};namespace {    place_holder_1 _1;}// Now this is validint main(){    std::vector<int> my_ints;    /* fill the vector */    std::for_each(my_ints.begin(), my_ints.end(), _1 + 4 + (-_1));}


The main thing thats missing there is operator= but it would simply return a lambda_expression< binary_op<assign_op, LHS, RHS> > and assign_op would assign its right argument to operator() to its left, doing that would require you change some of the template paramaters to be by reference ofcoarse.

If theres anything you want me to explain in more detail just let me know.
Thanks for that.. I was just playing around with templates and your comments make good sense. I need to re-structure it a bit.

And I got the unary operator- going..

Just did,
Expr<A,B> operator-(void) {
Expr<A,B> expression(0,*this,"-");
return expression;
}

Again, thanks to all those who took time to read this and thanks julian. Just getting used to templates, they are sharp.

This topic is closed to new replies.

Advertisement