Hello people,

Alright, my problem is something like this. I've declared a nested struct within a class template, and i want one of the member functions of the class to return an object of type struct. Somehow, i seem to be unable to do this defining the member function outside the class, but it does seem to work if i define the function within the class.

The actual code is quite involved, so i've contrived a little example to explain my problem:

#include <iostream>

template<class T>
class Tree {
    struct Node { int a, b; };
    Node createNode();
    T b;
};


template<class T>
Node Tree<T>::createNode() {
    std::cout<<"how are you\n";
    Node n; n.a=n.b=10;
    return n;
}

function createNode() is the problem here. Return type Node doesn't work. Return type Tree<T>::Node doesn't work. I've broken my head over this for quite a while, and am out of ideas. I'm using the Mingw compiler on Windows if that's of any relevance. The errors i get are something like:

expected constructor, destructor, or type conversion before "Tree"

Any help will be greatly appreciated. Thank you in advance.

This works with VC6:

#include <iostream>

template<class T> class Tree 
{
public:
    struct Node { int a, b; };
	Node createNode();

private:
	T b;
};


template<class T> Tree<T>::Node Tree<T>::createNode()
{
    std::cout<<"how are you\n";
    Node n; n.a=n.b=10;
    return n;
}



int main(int argc, char* argv[])
{
	Tree<int> tree;
	Tree<int>::Node n = tree.createNode();
	n.a;
	return 0;
}

U did not mention what kind of tree u r trying to code. So I suppose that you r trying to code a binary tree. In such case u could use the following:

#include <iostream>

//The binary tree class template
template<class T> class aBTclass
{
public:

//--Constructors and operations-----------------------
//--Construct an empry binary tree
	aBTclass():root(NULL) {}
    //follows the nested data type: a binary tree node
	template<class T> 
	struct aBTNode		
	{
		//Data fields of the aBTNode
		//The node consists of a data part and 2 links to its successor nodes
		T data;								
		aBTNode<T>* leftSubtree;			
		aBTNode<T>* rightSubtree;			

		//The constructor of the aBTNode
		aBTNode(const T& the_data,			/
				aBTNode<T>* left=NULL,		
				aBTNode<T>* right=NULL) :	
		data(the_data),leftSubtree(left),rightSubtree(right) {
			std::cout<<"Constructor of the aBTNode is used"<<std::endl;	}
		//The Destructor of the aBTNode
		virtual ~aBTNode() {std::cout<<"Destructor of the aBTNode is used"<<std::endl;	}


	};//End of the binary tree node

protected:
	aBTNode<T>* root;						//aBTNode<int>* root;
//I leave the rest for u... lol lol
};

int main(int argc, char* argv[])
{
	aBTclass<int> tree;
	return 0;
}

As u can see the node is made using a constructor.
Hope I helped u

You mentioned that you attempted a return type of Tree<T>::Node , However, that's not sufficient for the compiler to take your word for it that Node is indeed a type identifier and not something else.

The issue is that Tree<T> is an incomplete type, where Tree::Node could be absolutely anything depending on the specialisation of Tree<T>

The solution is to use the typename keyword to give the compiler the extra hint that Tree<T>::Node is indeed a type

template<class T>
class Tree {
    struct Node { int a, b; };
    Node createNode();
    T b;
};


template<class T>
typename Tree<T>::Node Tree<T>::createNode() {
    std::cout<<"how are you\n";
    Node n; n.a=n.b=10;
    return n;
}

You mentioned that you attempted a return type of Tree<T>::Node , However, that's not sufficient for the compiler to take your word for it that Node is indeed a type identifier and not something else.

The issue is that Tree<T> is an incomplete type, where Tree::Node could be absolutely anything depending on the specialisation of Tree<T>

The solution is to use the typename keyword to give the compiler the extra hint that Tree<T>::Node is indeed a type

template<class T>
class Tree {
    struct Node { int a, b; };
    Node createNode();
    T b;
};


template<class T>
typename Tree<T>::Node Tree<T>::createNode() {
    std::cout<<"how are you\n";
    Node n; n.a=n.b=10;
    return n;
}

Ah, that nailed it. Many thanks Bench. I realized it was some name resolution issue that specifically concerned, but i wasn't too sure, and i haven't had the time to read up any additional stuff, but i just did, and it makes perfect sense.

I guess this problem is solved.

This question has already been answered. Start a new discussion instead.