Member function definition outside of class body results in error - c++

I am pretty new to the concept of templates. Am I missing something?
#ifndef STACK_H
#define STACK_H
template < class T>
class Stack{
private:
struct node {
T data;
node* next;
};
node * top;
//node* getNewNode(T num);
};
//template <class T>
//(node*)Stack<T> :: getNewNode(T num){
// node * temp = new node;
// temp->data = num;
// temp->next = NULL;
// return temp;
// }
#endif
When I uncomment the function getNewNode and commend the corresponding statement to getNewNode function, complier gives error like
Why is my function getNewNode not working as expected. Where did I go wrong?
Error 7 error C2470: 'Stack<T>::getNewNode' : looks like a function
definition, but there is no parameter list; skipping apparent
body c:\users\nitinjose\documents\visual studio
2010\projects\templatequeue\templatequeue\stack.h 26 1 TemplateQueue
Error 2 error C4430: missing type specifier - int assumed. Note: C++
does not support default-int c:\users\nitinjose\documents\visual
studio
2010\projects\templatequeue\templatequeue\stack.h 26 1 TemplateQueue
Error 5 error C2146: syntax error : missing ')' before identifier
'num' c:\users\nitinjose\documents\visual studio
2010\projects\templatequeue\templatequeue\stack.h 26 1 TemplateQueue

Defining a member function outside of a class body changes the rules for what names are accessible at that point slightly. In your case the compiler has no idea what node is. You need to tell him that the node* is actually in the class Stack<T>, e.g. typename Stack<T>::node. The typename is necessary here, because node is a dependent name.

The specification of the return value is wrong. Try this
template <class T>
typename Stack<T>::node* Stack<T> :: getNewNode(T num){
// ...
}

Related

Implementing a Skip List, syntax error : missing ')' before ';'

I'm having this problem, where I get weird syntax errors in my skip list implementation and seriously have no clue what could cause this.
This is the code:
skipnode.h:
template <typename T>
class SkipNode
{
public:
T data;
SkipNode<T> **next;
SkipNode(T d, int level);
~SkipNode();
};
skipnode.cpp
#include "skipnode.h"
template<typename T>
SkipNode<T>::SkipNode(T d, int level)
{
data = d;
next = new SkipNode<T>*[level];
for (int i = 0; i <= level; i++)
next[i] = 0;
}
template<typename T>
SkipNode<T>::~SkipNode()
{
delete [] next;
}
Skiplist.h
#include "skipnode.cpp"
#define MAXLEVEL 4;
template<typename T>
class SkipList
{
public:
SkipList();
~SkipList();
int randLvl(int max);
T search(T);
void insert(T);
private:
SkipNode<T> *root;
};
Skiplist.cpp
#include "skiplist.h"
template<typename T>
SkipList<T>::SkipList()
{
root = new SkipNode<T>(0,MAXLEVEL);
}
When I declare root in Skiplist() I get the following error:
error C2143: syntax error : missing ')' before ';'
Can anyone help me out? Thanks in advance.
Edit: Fixed code, so show includes
The root cause of your problem is here:
#define MAXLEVEL 4;
The semicolon is present in the macro expansion, so after the preprocessor pass you end up with:
root = new SkipNode<T>(0, 4;);
Which is a syntax error (extra semicolon before the closing parenthesis).
To fix it, omit the semicolon in your macro definition:
#define MAXLEVEL 4
You need to include skipnode.h, or at least declare
template <typename T> class SkipNode;
before you can use the name SkipNode in the definition of SkipList.
You'll also (almost certainly) need to define the template member functions in your headers, not source files, as explained here.
You also have a problem with
#define MAXLEVEL 4;
which will expand to 4;, inserting a rogue ; in the middle of an expression. Use a less broken macro
#define MAXLEVEL 4
or, better still, a language-level constant
const int max_level = 4;

error: ‘List’ is not a template type

I am a beginner in c++ so please excuse me if I my mistakes below turn out to be silly. Still, I am stuck with my code and would appreciate any help.
I get the following error when trying to compile through make via g++:
In file included from A.cpp:2:
List.h:20: error: ‘List’ is not a template type
A.cpp: In member function ‘void A::NowyObiekt(int)’:
A.cpp:6: error: ‘list_a’ was not declared in this scope
make: *** [A.o] Error 1
My code is separated into the following tiny files:
A.h : http://pastebin.com/QQ04xx2j (header)
A.cpp : below
#include "A.h"
#include "List.h"
void A::NewObject(int i)
{
list_a.Add(i);
}
int A::Compare(int a, int b)
{
if ( a>b ) return 1;
if ( a<b ) return -1;
else return 0;
}
List.h : below (header)
#ifndef LIST_H
#define LIST_H
template<typename T>
class Node
{
Node()
{
nxt = pre = 0;
}
Node(const T& el, Node *n = 0, Node *p = 0 )
{
dana = el; nxt = n; pre = p;
}
T dana;
Node *nxt, *pre;
};
template<typename T>
class List
{
public:
List()
{
head = tail = 0;
}
void Add(const T&);
protected:
Node<T> *head,*tail;
};
#endif
List.cpp : http://pastebin.com/a3HQ9yZ4
prog.cpp : below (main)
#include "List.h"
#include "A.h"
int main()
{
int i = 5;
class List list_a;
class A obj;
obj.Add(i);
}
and the makefile is : http://pastebin.com/GTR5jW54
As noted, I am still a beginner, so please be understanding. I would be thankful for any help and clear explanations. Thanks in advance.
There are a couple of problems with your code: The first is that you don't declare any variable named list_a anywhere. That error should be pretty obvious. The other is that you use the List class without giving it template parameters.
And last a small note about your question: As your files are indeed very small, you could put them in the question and not link to them.
Edit: About the List template problem.
You already use Node properly in List, i.e. declare the nodes as Node<T>. When you use List you simply has to do the same. For example, to declare a list of integers:
List<int> my_int_list;
Also, as you only use public functions in List from the class A, you don't need the friend declaration. If you do need to use protected or private members (which IMO is a sign of bad design) you need to make that friend-declaration templated as well:
friend class List<sometype>;
And finally, your code will not compile anyway... The reason being that when you are using a template-class, the whole class has to be fully defined (i.e. complete with its function implementations). You can solve this by putting the functions in the header file. And when defining the functions, you need the template parameter there as well:
template<typename T>
void List<T>::Add(const T& el)
{
Node<T>* head = new Node<T>(el);
if ( Compare(el,i) > i )
std::cout << "Ok" << std::endl;
}
Note that I added the template parameter in a couple of places.

C++ static const template member initialization

I'm having some strange issues trying to initialize a static const member variable of a template class. All of my other static variables initialize fine but for some reason it doesn't like this one. I put together some sample code to test and it doesn't have the problem so I really don't know what's going on.
On top of this I'm also having issues defining functions that use typedefs declared inside of the template class with the same issue saying it can't find the type. This problem I have been able to reproduce though in the code below. I know one way to fix it is to define the function inside of the class, but the function is really large and I'm trying to keep it consistent with having all of the huge functions defined outside of the class to make the class definition easier to read. If that's my only option though then I guess I'll have to make an exception...
class tTestType
{
public:
tTestType(int32_t val) : fValue(val) { }
private:
int32_t fValue;
};
template<class T>
class tTestTemplate
{
public:
tTestTemplate() { }
private:
typedef std::vector<int32_t> tSomeVec;
tSomeVec mTestFunction() const;
static const tTestType kTestStatic;
};
// Should cause the following errors but I can't reproduce them for some reason:
// error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
// error C2988: unrecognizable template declaration/definition
// error C2059: syntax error : 'constant'
template<class T>
const tTestType tTestTemplate<T>::kTestStatic(10);
// Causes the following errors:
// error C2143: syntax error : missing ';' before 'tTestTemplate<T>::mTestFunction'
// error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
// fatal error C1903: unable to recover from previous error(s); stopping compilation
template<class T>
tTestTemplate<T>::tSomeVec tTestTemplate<T>::mTestFunction() const
{
tSomeVec result;
result.push_back(0);
return result;
}
Thanks to a coworker I've figured out a solution to both issues.
For the first issue, the static member variable, I've moved the definition to the CPP file and used a template specialization. The reason this doesn't break in the test code I posted is because the basic type (int, float, etc.) handle the problem, but if you use a more complex type, like a class, then it should cause the error. This solution isn't the best thing in the world to do, I know, but it's the only thing that works that is somewhat clean. If someone has a better solution please let me know:
template<>
const tTestType tTestTemplate<uint32_t>::kTestStatic(10);
For the second issue, the function using a type declared inside the class, I went with the solution I described in the initial post and just moved the function definition inside of the template class so now it looks like this:
template<class T>
class tTestTemplate
{
public:
tTestTemplate() { }
private:
typedef std::vector<int32_t> tSomeVec;
// Declaring the function inside the class to fix the compiler error.
tSomeVec mTestFunction() const
{
tSomeVec result;
result.push_back(0);
return result;
}
static const tTestType kTestStatic;
};
I made 2 changes in your code and its compiling fine.
class tTestType
{
public:
tTestType(int32_t val) : fValue(val) { }
private:
int32_t fValue;
};
typedef std::vector<int32_t> tSomeVec;
template<class T>
class tTestTemplate
{
public:
tTestTemplate() { }
private:
tSomeVec mTestFunction() const;
static const tTestType kTestStatic;
};
// Should cause the following errors but I can't reproduce them for some reason:
// error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
// error C2988: unrecognizable template declaration/definition
// error C2059: syntax error : 'constant'
template<class T>
const tTestType tTestTemplate<T>::kTestStatic(10);
// Causes the following errors:
// error C2143: syntax error : missing ';' before 'tTestTemplate<T>::mTestFunction'
// error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
// fatal error C1903: unable to recover from previous error(s); stopping compilation
template<class T>
tSomeVec tTestTemplate<T>::mTestFunction() const
{
tSomeVec result;
result.push_back(0);
return result;
}

Error: expected unqualified-id before ‘<’ token

I am trying to make some sort of templated Queue class. It seems ok but I am getting 2 errors in the same line which I can't figure out why. The errors appear in the implementation file .cpp where I am trying to give the definition for the destructor. Here is the code of the header file of the class:
#ifndef QUEUETP_H_INCLUDED
#define QUEUETP_H_INCLUDED
template <class T>
class QueueTp
{
private:
struct Node { T item; struct Node * next;};
enum {QSIZE = 10};
//Queue's head
Node *head;
//Queue's tail
Node *tail;
int size;
int maxsize;
QueueTp(const QueueTp & q);
QueueTp & operator=(const QueueTp & q) { return *this;}
public:
QueueTp(): size(0),head(0),tail(0),maxsize(QSIZE) {};
QueueTp(int q = QSIZE): size(0),head(0),tail(0),maxsize(q) {};
~QueueTp();
bool isEmpty(){return size==0;}
bool isFull() {return size==maxsize;}
int sizecur() {return size;}
bool push(const T& t);
bool pop(T& t);
};
#include "QueueTp.cpp"
#endif // QUEUETP_H_INCLUDED
And here is the definition of the destructor in the implementation file:
#include "QueueTp.h"
#include <iostream>
using namespace std;
typename <class T> //<-<-<- in this line I am getting the two errors
QueueTp<class T>::~QueueTp()
{
Node *ptr;
cout<<endl<<"Deleting the queue...";
while (head !=NULL)
{
ptr = head->next;
delete head;
head = ptr;
}
}
//......other method definitions
The errors are pointed above and the specific error messages I get from the compiler are the ones below.
error: expected nested-name-specifier before ‘<’ token|
error: expected unqualified-id before ‘<’ token|
||=== Build finished: 2 errors, 12 warnings ===||
Please use "template" instead of "typename" on the line where you are getting the two error messages! I find that most of the time, an unidentified keyword or a real keyword in the wrong place often gives errors similar to an undefined type, the next symbol after it would cause an error.

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.
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.
template <class T>
typename ItemCollection <T>::Item* ItemCollection<T>::insert( T p, Item* ptr)
{
// function body
}