Variable is not declared even it is

104 views Asked by At

I have some (simple looking?) problem with the variable declaration in template friend operator overloading. The compiler gives me a message:

main.cpp|103|error: ‘ptemp’ was not declared in this scope|

Code:

template <typename K, typename I>
class Sequence
    {
    private:
         struct Data
         {
            K key;
            I data;
            Data *pnext;
          };

     Data *pHead;
    public:
    //(...)
    friend ostream &operator << <I,K> (ostream&, const Sequence<I,K>&);
    };



    template <typename I, typename K>
    ostream &operator << (ostream& stream, const Sequence<I,K> &cop)
    {
     Sequence<I,K>::Data *ptemp (cop.pHead); ///here is the error (?)

        stream << "-------------- PRINT BEGINS ---------------" << endl;
        if (!ptemp) //there is no elements
        {
        stream << "The list is empty, there is nothing to print!" << endl;
        stream << "--------------  PRINT ENDS  ---------------" << endl << endl;
        return stream;
        };
    }

Compilers gives message that there is no declarated "ptemp" when I do a declaration. The same is when I erase initialization of ptemp. I can't understand what is wrong in this declaration. I will be grateful for any suggestions.

3

There are 3 answers

3
Vlad from Moscow On BEST ANSWER

Try the following

typename Sequence<I,K>::Data *ptemp (cop.pHead); 
0
Mark B On

The problem appears to be that Sequence<I,K>::Data is a dependent name and the compiler needs help from the typename keyword to know what to do. So you would need to say typename Sequence<I,K>::Data *ptemp(cop.pHead); instead. I can't figure out how it's interpreting it without the keyword though (my first guess, as a function declaration via most vexing parse doesn't appear to be correct as changing to an = in the initialization didn't fix it).

Also as an aside it appears that your inline friend declaration may be a compiler-specific extension that should probably be avoided. I had to make multiple changes to your code to get to the point of reproducing the error in the question with g++ 4.5.

0
leemes On

The name Sequence<I,K>::Data depends on the definition of I and K: the compiler can't know if Data is a type or a non-type (i.e. a value) in the template instance Sequence<I,K>. So you need to tell the compiler that it is a type by prepending the keyword typename, otherwise it assumes it is a non-type, so the line is parsed as a multiplication of two values, of which the second isn't known. For a detailed explanation please refer to "Where and why do I have to put the “template” and “typename” keywords?".

typename Sequence<I,K>::Data *ptemp (cop.pHead);

If you can use C++11, you can replace the full type with auto:

auto ptemp = cop.pHead;

Also, you can put the friend non-member definition directly inside the class (which does not make it a member!). Then you can refer to Sequence<I,K> simply with Sequence and to your sub-type Data simply as Data:

public:
    friend ostream &operator << (ostream& stream, const Sequence &cop)
    {
        Data *ptemp (cop.pHead);
        ...
    }