juniorro
juniorro

Reputation: 47

Variable is not declared even it is

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.

Upvotes: 1

Views: 88

Answers (3)

leemes
leemes

Reputation: 45675

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);
        ...
    }

Upvotes: 0

Mark B
Mark B

Reputation: 96241

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.

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 310990

Try the following

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

Upvotes: 3

Related Questions