3

This is my very first question on StackOverflow. I've searched for similar "Identifier not Found" errors but couldn't find anything helpful. I'll be grateful for your help since I've been trying to work this out for 2 hours with no results.

It basically creates an object of type "Addition" and prints "1 + 1 = 2" (if it worked).

When I was not using templates it was working fine. But when I changed everything to templates it stopped working. I couldn't figure this out.

Visual studio does not underline anything in red, however I get a "identifier not defined" error for m_Argument_1 and m_Argument_2.

Thank you for your help and I apologize if this is a too simple question to ask here, but nevertheless I couldn't find a way out or figure out where the problem is.

This is my header file "Expression.h":

#ifndef OPERATION_HEADER
#define OPERATION_HEADER

#include <string>
#include <iostream>

template <typename T>
class Expression
{
protected: 

    char m_ExpressionSign; /* Represents Expression's Sign ('+','-','*','/') */

    T m_Argument_1; /* Represents L Argument */
    T m_Argument_2; /* Represents R Argument */

public: 

    Expression(T arg_1, T arg_2, char expressionSign) : m_Argument_1(arg_1), m_Argument_2(arg_2), m_ExpressionSign(expressionSign) { };

    virtual T Result() const = 0;

    virtual void Print(std::ostream& out) const;

    friend std::ostream& operator << (std::ostream& out, const Expression<T>& expression);
};

template <typename T>
class Addition : public Expression<T>
{
public:
    Addition(T arg1, T arg2) : Expression<T>(arg1, arg2, '+') {};
    T Result() const { return m_Argument_1 + m_Argument_2; };
};

template <typename T>
void Expression<T>::Print(std::ostream& out) const
{
    out << m_Argument_1 << " " << m_ExpressionSign << " " << m_Argument_2 << " = ";
}

template <typename T>
std::ostream& operator << (std::ostream& out, const Expression<T>& expression)
{
    expression.Print(out);
    return out;
}

#endif /* OPERATION_HEADER */

And this is my main.cpp:

#include <iostream>
#include <iomanip>

#include "Expression.h"

int main(int argc, char** argv)
{
    Addition<int> A2(1, 1); 

    std::cout << "A2: " << A2 << " = " << std::setw(2) << A2.Result() << std::endl;
    retun 0;
}
Muratcan Akcay
  • 155
  • 2
  • 12
  • 1
    Try putting `this->` in front of those variables you're having trouble with. Then someone will link to a duplicate, since I am sure this has been answered before. – PaulMcKenzie Jun 02 '20 at 18:46

1 Answers1

3

When inheriting from a class template, identifiers need to be qualified so that the compiler knows where they come from. In this case, in the definition of Addition, you could do:

T Result() const { return this->m_Argument_1 
                        + this->m_Argument_2; };

Alternatively, you could qualify the names like this:

T Result() const { return Expression<T>::m_Argument_1 
                        + Expression<T>::m_Argument_2; };
cigien
  • 57,834
  • 11
  • 73
  • 112
  • there is also a problem with the friend operator overload no? – yaodav Jun 02 '20 at 18:52
  • Thank you! Tha "almost" worked, but now I'm getting an error related to ostream :( `1>main.obj : error LNK2019: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,class Expression const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$Expression@H@@@Z) referenced in function _main 1>C:\CodeBase\VS19\Prog2\2020 Labs\Debug\Test.exe : fatal error LNK1120: 1 unresolved externals` – Muratcan Akcay Jun 02 '20 at 18:54
  • @yaodav No, names declared inside a template class are fine, it's only inherited members that need to be qualified. – cigien Jun 02 '20 at 18:54
  • try comment the friend line like this:`'//friend std::ostream& operator << (std::ostream& out, const Expression& expression);` – yaodav Jun 02 '20 at 18:56
  • @yaodav Yes! It worked. But why? Why is that friend declaration troublesome? – Muratcan Akcay Jun 02 '20 at 18:58
  • That friend declaration ends up not actually defining the `operator<<` for `int` specialization. You can solve this problem by defining the `friend operator<<` *inside* the class. – cigien Jun 02 '20 at 19:03
  • @MuratcanAkçay read [this](https://stackoverflow.com/questions/2828280/friend-functions-and-operator-overloading-what-is-the-proper-way-to-overlo) it will explain – yaodav Jun 02 '20 at 19:03
  • @yaodav that doesn't cover the issue with `operator<<` as a friend of a class *template*. – cigien Jun 02 '20 at 19:05