Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template and pointers

I have a problem with a template and pointers ( I think ). Below is the part of my code:

/* ItemCollection.h */

#ifndef ITEMCOLLECTION_H
#define ITEMCOLLECTION_H

#include <cstddef>

   using namespace std;

   template <class T> class ItemCollection
   {
   public:
    // constructor
        //destructor 

     void insertItem( const T );

   private:
         struct Item
         {
          T price;
          Item* left;               
          Item* right;          
         };
         Item* root;     
         Item* insert( T, Item* );

   };
 #endif

And the file with function defintion:

/* ItemCollectionTemp.h-member functions defintion */

#include <iostream>
#include <cstddef>

#include "ItemCollection.h"

template <class T>
   Item* ItemCollection <T>::insert( T p, Item* ptr)
   {
      // function body
   }

Here are the errors which are generated by this line of code:

Item* ItemCollection <T>::insert( T p, Item* ptr)

Errors:

error C2143: syntax error : missing ';' before '*'

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

error C2065: 'Type' : undeclared identifier

error C2065: 'Type' : undeclared identifier

error C2146: syntax error : missing ')' before identifier 'p'

error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

error C2470: 'ItemCollection::insert' : looks like a function definition, but there is no parameter list; skipping apparent body

error C2072: 'ItemCollection::insert': initialization of a function

error C2059: syntax error : ')'

Any help is much appreciated.

like image 714
Kary Avatar asked Dec 17 '22 01:12

Kary


2 Answers

The short answer is what Alexey already posted:

template <typename T>
typename ItemCollection<T>::Item* ItemCollection<T>::insert( T p, Item * ptr ) {
   // ...
}

(To understand why typename is required, search SO for related questions, or else drop a comment. I will focus the answer in the lookup rules that explain why the return and the argument types must be declared differently)

The explanation is that the lookup rules in c++ have different scopes for the return type and the rest of the parameters. When the compiler sees the definition A B::c( D ), A is checked in the enclosing namespace of the definition, as is B. When the compiler finds ::c it looks up c inside class B. At that point, the rest of the definition is inside the scope of the class B for the rest of parameters. That means that if the return type is an internal type of the class, you have to use the qualified name for the return type, while in the case of D the compiler will first look it up inside the class B.

That explains why the return type must be fully qualified even if the last parameter is not. When the parameter Item * ptr is found by the compiler, it is already in the scope of the class, and it will find it there. On the other hand, there is no Item defined in the enclosing namespace.

One of the changes in the upcomming standard will deal with this, even if it was not designed with this purpose in mind. If I recall correctly, the following syntax should compile without the full type qualification:

template <T>
auto ItemCollection<T>::insert( T p, Item * ptr ) -> Item *
{
   return 0;
}

The reason is exactly the same. After ItemCollection<T>::insert has been parsed the remainder tokens will be verified inside the ItemCollection<T> scope, including the -> Item * return definition.

like image 142
David Rodríguez - dribeas Avatar answered Dec 24 '22 01:12

David Rodríguez - dribeas


template <class T> 
   typename ItemCollection <T>::Item* ItemCollection<T>::insert( T p, Item* ptr) 
   { 
      // function body 
   } 
like image 27
Alexey Malistov Avatar answered Dec 24 '22 02:12

Alexey Malistov