template class won't compile after adding a destructor

E

Ethan

//eylds.h

#ifndef _EYL_DS_H_
#define _EYL_DS_H_

#include <cstdlib>
#include <algorithm>
#include "crtp.h"
using eylcrtp::Comparable;

enum direction_t {LEFT=0, RIGHT=1};

template <class KeyType, class DataType> class AvlNode;
template <class KeyType, class DataType> class AvlTree;
typedef AvlNode<class KeyType, class DataType> NodeType;

template <class KeyType, class DataType>
class AvlNode : public Comparable< AvlNode<KeyType, DataType> > {
public:

enum {MAX_SUB = 2};
AvlNode(KeyType k, DataType d) : _key(k), _data(d) { reset(); }

/* ************************************** problem here
**************************************
~AvlNode() {
if (_subNodes
) delete _subNodes
;
if (_subNodes
) delete _subNodes
;
}

**************************************************************************************************
*/


bool operator<(const AvlNode& a) const { return _key < a._key; }
KeyType key() { return _key; }
DataType data() { return _data;}
NodeType* child(direction_t d) { return _subNodes[d]; }
short bal() { return _bal; }

void reset() { _bal = 0; _subNodes
= NULL; _subNodes
=
NULL;}

friend class AvlTree<KeyType, DataType>;

private:
KeyType _key;
DataType _data;
short _bal;
NodeType* _subNodes[MAX_SUB];
};

template <class KeyType, class DataType>
class AvlTree {
public:
AvlTree() : _root(NULL) {}
~AvlTree() { if (_root) delete _root; }

private:
NodeType* _root;
};

#endif


//main.cc
#include <iostream>
#include "eylds.h"
using namespace std;

int main() {
int a = 5;
int *p1 = &a;

int b = 6;
int *p2 = &b;
AvlNode<int, int*> n1(a, p1);
AvlNode<int, int*> n2(b, p2);

cout << (n1 == n2) << endl;

return 0;
}

these code compiled and run ok.


But if I added the destructor, (the one commented out above), it
wouldn't compile

eylds.h: In instantiation of ‘AvlNode<KeyType, DataType>’:
eylds.h:22: instantiated from ‘AvlNode<KeyType, DataType>::~AvlNode
() [with KeyType = int, DataType = int*]’
test_eylds.cc:11: instantiated from here
eylds.h:38: error: ‘AvlNode<KeyType, DataType>::_key’ has incomplete
type
eylds.h:13: error: forward declaration of ‘struct KeyType’
eylds.h:39: error: ‘AvlNode<KeyType, DataType>::_data’ has incomplete
type
eylds.h:13: error: forward declaration of ‘struct DataType’


I couldn't figure out why, thank you in advance for your help!​
 
E

Ethan

//eylds.h

#ifndef _EYL_DS_H_
#define _EYL_DS_H_

#include <cstdlib>
#include <algorithm>
#include "crtp.h"
using eylcrtp::Comparable;

enum direction_t {LEFT=0, RIGHT=1};

template <class KeyType, class DataType> class AvlNode;
template <class KeyType, class DataType> class AvlTree;
typedef AvlNode<class KeyType, class DataType> NodeType;

template <class KeyType, class DataType>
class AvlNode : public Comparable< AvlNode<KeyType, DataType> > {
public:

  enum {MAX_SUB = 2};
  AvlNode(KeyType k, DataType d) : _key(k), _data(d) { reset(); }

  /*  ************************************** problem here
**************************************
  ~AvlNode() {
    if (_subNodes
) delete _subNodes
;
    if (_subNodes
) delete _subNodes
;
  }

**************************************************************************************************
*/

  bool operator<(const AvlNode& a) const { return _key < a._key; }
  KeyType key() { return _key; }
  DataType data() { return _data;}
  NodeType* child(direction_t d) { return _subNodes[d]; }
  short bal() { return _bal; }

  void reset() { _bal = 0; _subNodes
= NULL; _subNodes
=
NULL;}

  friend class AvlTree<KeyType, DataType>;

private:
  KeyType _key;
  DataType _data;
  short _bal;
  NodeType* _subNodes[MAX_SUB];

};

template <class KeyType, class DataType>
class AvlTree {
public:
  AvlTree() : _root(NULL) {}
  ~AvlTree() { if (_root) delete _root; }

private:
  NodeType* _root;

};

#endif

//main.cc
#include <iostream>
#include "eylds.h"
using namespace std;

int main() {
  int a = 5;
  int *p1 = &a;

  int b = 6;
  int *p2 = &b;
  AvlNode<int, int*> n1(a, p1);
  AvlNode<int, int*> n2(b, p2);

  cout << (n1 == n2) << endl;

  return 0;

}

these code compiled and run ok.

But if I added the destructor, (the one commented out above), it
wouldn't compile

eylds.h: In instantiation of ‘AvlNode<KeyType, DataType>’:
eylds.h:22:   instantiated from ‘AvlNode<KeyType, DataType>::~AvlNode
() [with KeyType = int, DataType = int*]’
test_eylds.cc:11:   instantiated from here
eylds.h:38: error: ‘AvlNode<KeyType, DataType>::_key’ has incomplete
type
eylds.h:13: error: forward declaration of ‘struct KeyType’
eylds.h:39: error: ‘AvlNode<KeyType, DataType>::_data’ has incomplete
type
eylds.h:13: error: forward declaration of ‘struct DataType’

I couldn't figure out why, thank you in advance for your help!​



seems the problem is typedef AvlNode<class KeyType, class DataType>
NodeType;
if I don't use this typedef, it works when I replaced all 'NodeType'
by 'AvlNode<KeyType, DataType>'
but I still don't understand why :(
 
R

red floyd

//eylds.h

#ifndef _EYL_DS_H_
#define _EYL_DS_H_

#include <cstdlib>
#include <algorithm>
#include "crtp.h"
using eylcrtp::Comparable;

enum direction_t {LEFT=0, RIGHT=1};

template <class KeyType, class DataType> class AvlNode;
template <class KeyType, class DataType> class AvlTree;
typedef AvlNode<class KeyType, class DataType> NodeType;

Stop right there. template typedefs are not supported.
 
L

litb

//eylds.h
#ifndef _EYL_DS_H_
#define _EYL_DS_H_
#include <cstdlib>
#include <algorithm>
#include "crtp.h"
using eylcrtp::Comparable;
enum direction_t {LEFT=0, RIGHT=1};
template <class KeyType, class DataType> class AvlNode;
template <class KeyType, class DataType> class AvlTree;
typedef AvlNode<class KeyType, class DataType> NodeType;
template <class KeyType, class DataType>
class AvlNode : public Comparable< AvlNode<KeyType, DataType> > {
public:
  enum {MAX_SUB = 2};
  AvlNode(KeyType k, DataType d) : _key(k), _data(d) { reset(); }
  /*  ************************************** problem here
**************************************
  ~AvlNode() {
    if (_subNodes
) delete _subNodes
;
    if (_subNodes
) delete _subNodes
;
  }
**************************************************************************************************
*/

  bool operator<(const AvlNode& a) const { return _key < a._key; }
  KeyType key() { return _key; }
  DataType data() { return _data;}
  NodeType* child(direction_t d) { return _subNodes[d]; }
  short bal() { return _bal; }​

  void reset() { _bal = 0; _subNodes
= NULL; _subNodes
=
NULL;}​

  friend class AvlTree<KeyType, DataType>;
private:
  KeyType _key;
  DataType _data;
  short _bal;
  NodeType* _subNodes[MAX_SUB];

template <class KeyType, class DataType>
class AvlTree {
public:
  AvlTree() : _root(NULL) {}
  ~AvlTree() { if (_root) delete _root; }
private:
  NodeType* _root;


//main.cc
#include <iostream>
#include "eylds.h"
using namespace std;
int main() {
  int a = 5;
  int *p1 = &a;
  int b = 6;
  int *p2 = &b;
  AvlNode<int, int*> n1(a, p1);
  AvlNode<int, int*> n2(b, p2);
  cout << (n1 == n2) << endl;
  return 0;

these code compiled and run ok.
But if I added the destructor, (the one commented out above), it
wouldn't compile
eylds.h: In instantiation of ‘AvlNode<KeyType, DataType>’:
eylds.h:22:   instantiated from ‘AvlNode<KeyType, DataType>::~AvlNode
() [with KeyType = int, DataType = int*]’
test_eylds.cc:11:   instantiated from here
eylds.h:38: error: ‘AvlNode<KeyType, DataType>::_key’ has incomplete
type
eylds.h:13: error: forward declaration of ‘struct KeyType’
eylds.h:39: error: ‘AvlNode<KeyType, DataType>::_data’ has incomplete
type
eylds.h:13: error: forward declaration of ‘struct DataType’
I couldn't figure out why, thank you in advance for your help!

seems the problem is typedef AvlNode<class KeyType, class DataType>
NodeType;
if I don't use this typedef, it works when I replaced all 'NodeType'
by 'AvlNode<KeyType, DataType>'
but I still don't understand why :(


"class X" is an elaborated type specifier. In a declaration, you
basically have different specifiers. some specifiers are type
qualifiers (const, volatile), some are simple type specifiers (int,
unsigned, ...) and some are elaborated type specifiers (class X, union
F) and you can of course just name a type previously declared "F"
instead of "class F" if F is already known to be a class name.

If you use that kind of elaborated type specifier, what happens is
that the name is made known as a class name and the whole specifier
names that class type then. If it wasn't known before, it will be a
new, incomplete type. That's your case. Your stuff is just the same as
saying

class KeyType;
class DataType;

typedef AvlNode<KeyType, DataType> NodeType;

They do *not* name template parameters. But they name new, incomplete
types. You cannot typedef a template like that. Wait for the next C++
Standard (which will take its own time to be implemented by compiler
vendors) and you can do

template<class KeyType, class DataType>
using NodeType = AvlNode<KeyType, DataType>;

Hope this helps.​
 
J

James Kanze

//eylds.h
#ifndef _EYL_DS_H_
#define _EYL_DS_H_
#include <cstdlib>
#include <algorithm>
#include "crtp.h"
using eylcrtp::Comparable;
enum direction_t {LEFT=0, RIGHT=1};
template <class KeyType, class DataType> class AvlNode;
template <class KeyType, class DataType> class AvlTree;
typedef AvlNode<class KeyType, class DataType> NodeType;

What's this line supposed to mean? It doesn't correspond to any
C++ syntax I know. (Curiously, g++ seems to accept it without
an error message. Looks like a bug in g++ to me.)

I couldn't try more, since I don't have "crtp.h", and I don't
know what eylcrtp::Comparable is. (I deleted all but the three
lines above for my quick test.)
 
A

Alf P. Steinbach

* James Kanze:
What's this line supposed to mean? It doesn't correspond to any
C++ syntax I know. (Curiously, g++ seems to accept it without
an error message. Looks like a bug in g++ to me.)

Seems OK technically. As noted earlier, else-thread, by "litb", it's just use of
elaborated type identifiers. It's not a template typedef.

So, being technically OK, that part compiles fine with e.g. Comeau.

But some confusion that it would be a template typedef is probably the problem,
as "litb" noted.


Cheers & hth.,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top