Gunter Don - 1 year ago 49

C++ Question

I have a template class that just seems to fail this on one test.

- There is a template structure "term" representing the node values of an expression graph.
- There is a template structure "expression" representing the graph.
- There is a test procedure "void Test()"

I have beat my head for a few hours now. I would really like some assistance.

`void Test()`

{

cout << "**** Integer Tests" << endl;

// Default Constructor

integer a;

cout << "integer a = "<< a.Value << endl;

// Copy Constructor

integer b(a);

cout << "integer b(a) = "<< b.Value << endl;

integer c = b;

cout << "integer c = b = "<< c.Value << endl;

// Type Constructor

integer d(5);

cout << "integer d(5) = "<< d.Value << endl;

integer e = 5;

cout << "integer e = 5 = "<< e.Value << endl;

// Type Conversions

int n = e.Value;

cout << "n = e = "<< n << endl;/

n = (int)d.Value + (int)e.Value;

cout << "n = d + e = "<< n << endl;// allowed because a convers to int

cout << "**** Expression Tests" << endl;

expression<int> e1;

expression<int> e2(e1);

expression<int> e3(d);// This line using the copy constructor works

expression<int> e4 = d + e;// this line, using the copy constructor AFTER the operator+ call results in BUM values.

}

The test function "void Test()" fails to give the correct value for the statement :

expression e4 = d + e;

stepping through the call stack...at T+1

1.) calls term::expression& operator+(term& ref)

2.) on return, the left and right values of the expression node are CORRECT!!!

3.) now, the assignment that fails... it calls copy constructor expression(expression& ref)

4.) WTF??? inside this i get bum left and right values.

why, when the copy constructor test succeeds at the line above?

here are the test case templates

`template<typename T> struct expression; // Forward Declare expressions, so i can use it in operator+`

template<typename T>

struct term

{

T Value;

term() : Value(0)

{

cout << "**** term()" << endl;

} // Default Constructor

term(term& ref) : Value(ref.Value)

{

cout << "**** term(term& ref)" << endl;

} // Copy Constructor

// Type Conversion

term(T value) : Value(value)

{

cout << "**** term(T value)" << endl;

} // Type Constructor

//operator T() const { return Value; } // Type Converter

**expression<T>& operator+(term& ref)

{

return expression<T>(*this, ref);

};**

};

template<typename T>

struct expression

{

term<T> Left;

term<T> Right;

expression()

: Left()

, Right()

{

cout << "**** expression()" << endl;

cout << "left" << Left.Value << endl;

cout << "right" << Right.Value << endl;

}

expression(expression& ref)

: Left(ref.Left)

, Right(ref.Right)

{

cout << "**** expression(expression& ref)" << endl;

cout << "left" << Left.Value << endl;

cout << "right" << Right.Value << endl;

}

expression(term<T>& left)

: Left(left)

, Right()

{

cout << "**** expression(term<T>& left)" << endl;

cout << "left" << Left.Value << endl;

cout << "right" << Right.Value << endl;

}

expression(term<T>& left, term<T>& right)

: Left(left)

, Right(right)

{

cout << "**** expression(term<T>& left, term<T>& right)" << endl;

cout << "left" << Left.Value << endl;

cout << "right" << Right.Value << endl;

}

};

struct integer : public term<int>

{

integer() : term() { }// allows default constructor (not inheritablle)

// tactic to get base class constructors(1 parameter) to compile...

template<class T> integer(T t) : term(t) { }

//template<class T> integer(T& t) : term(t) { }

};

void Test()

{

cout << "**** Integer Tests" << endl;

// Default Constructor

integer a;

cout << "integer a = "<< a.Value << endl;// allowed because integer converts to int

// Copy Constructor

integer b(a);

cout << "integer b(a) = "<< b.Value << endl;

integer c = b;

cout << "integer c = b = "<< c.Value << endl;

// Type Constructor

integer d(5);

cout << "integer d(5) = "<< d.Value << endl;

integer e = 5;

cout << "integer e = 5 = "<< e.Value << endl;

// Type Conversions

int n = e.Value;

cout << "n = e = "<< n << endl;// allowed because a convers to int

// Arithmetic using base type operators... whatever they allow, is allowed.

n = (int)d.Value + (int)e.Value;

cout << "n = d + e = "<< n << endl;// allowed because a convers to int

cout << "**** Expression Tests" << endl;

expression<int> e1;

expression<int> e2(e1);

expression<int> e3(d);// This line using the copy constructor works

expression<int> e4 = d + e;// this line, using the copy constructor AFTER the operator+ call results in BUM values.

}

Output of the above code looks like:

`**** Integer Tests`

**** term()

integer a = 0

**** term(term& ref)

integer b(a) = 0

**** term(term& ref)

integer c = b = 0

**** term(T value)

integer d(5) = 5

**** term(T value)

integer e = 5 = 5

n = e = 5

n = d + e = 10

**** Expression Tests

**** term()

**** term()

**** expression()

left0

right0

**** term(term& ref)

**** term(term& ref)

**** expression(expression& ref)

left0

right0

**** term(term& ref)

**** term()

**** expression(term<T>& left)

left5

right0

**** term(term& ref)

**** term(term& ref)

**** expression(term<T>& left, term<T>& right)

left5

right5

**** term(term& ref)

**** term(term& ref)

**** expression(expression& ref)

left4061292

right4061296

The function was fixed such that the ampersand after expression was removed:

`expression<T> operator+(term& ref)`

{

return expression<T>(*this, ref);

};

This was an ID10T error. the ampersand was right there in front of me.

Again, Thanks for helping me resolve this.

Answer Source

Here's your problem:

```
expression<T>& operator+(term& ref)
```

`operator+`

should return a new object. You're returning a reference to a temporary. That should've even compile, but I'm guessing you're using MSVC which has an extension to allow this for reasons that I don't understand.

There's other problems in your code that should prevent it from compiling to, but that's likely the one that's causing your error. As a first approximation, every use of reference in your code is incorrect - they should all either be references to `const`

or values.