Explain to me, please, in what a mistake in the declaration/description of this method?
class Set
{
struct Node {
// ...
};
// ...
Node* &_getLink(const Node *const&, int) const;
// ...
};
Node* &Set::_getLink(const Node *const &root, int t) const
{
// ...
}
I don't see mistakes, but the compiler (MS VS C++) gives out many syntax errors.
You forgot to fully qualify the name of Node (which is defined in the scope of Set):
Set::Node* &Set::_getLink(const Node *const &root, int t) const
// ^^^^^
Without the fully qualification, the compiler will look for a global type named Node, which does not exist.
The problem is a scoping one. You need to prefix Node here:
Set::Node* &Set::_getLink(const Node *const &root, int t) const
{
// ...
}
Indeed, Node is unknown at the time it is encountered (you are at namespace scope, not inside Set's scope). You can also use auto:
auto Set::_getLink(const Node *const &root, int t) const -> Node *&
{
// ...
}
After ->, you are at Set's scope and Node is known.
you dont define Node in global scope
so use this code
//by Set::Node we give compiler that this function exist in class Node
Set::Node* &Set::_getLink(const Node *const &root, int t) const
{
// ...
}
Related
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed last month.
I am really sorry if this is a duplicate post, but I am really stuck on this particular problem. For some inexplicable reason the compiler does not understand what return type Node* is on the .cpp file, here is the code:
template<typename T>
Node* BinarySearchTree<T>::DiveDownToReplace(Node* node) {
if (node->leftChild->rightChild == nullptr) {
return node->leftChild;
}
//otherwise
Node* traversingNode = node->leftChild;
Node* returnedNode;
while (true) {
if (traversingNode->rightChild->rightChild == nullptr) {
returnedNode = traversingNode->rightChild;
traversingNode->rightChild = returnedNode->leftChild;
returnedNode->leftChild = nullptr;
break;
}
traversingNode = traversingNode->rightChild;
}
return returnedNode;
}
Here is also the code in the .h(header file):
#pragma once
template<typename T>
class BinarySearchTree {
private:
struct Node
{
T data;
Node* leftChild;
Node* rightChild;
};
int m_Length = 0;
Node* root = new Node();
public:
enum class TraverseMethod
{
preorder,
inorder,
postorder,
levelorder
};
~BinarySearchTree();
void AddElement(T value);
T RemoveRoot();
bool RemoveElement(T value);
void PrintAllElements(TraverseMethod traverseMethod);
bool IsEmpty();
bool GetSize();
bool Contains(T value);
private:
void PreOrder(Node* node);
void InOrder(Node* node);
void PostOrder(Node* node);
void LevelOrder(bool deleteNode = false);
void DiveDownToAdd(T value, Node* node);
Node* DiveDownToReplace(Node* node);
};
I am getting the error "identifier Node is undefined". I tried adding BinarySearchTree::Node* instead of Node*, but I received some weird errors(c2061, syntax error: identifier 'Node'). Once more I am sorry if this post is duplicate, but coming from languages like c# and Java I am really fed up with these header issues. Thank you in advance!
There are two rather complicated technical details of C++ that get combined together here. First of all, is scoping and namespaces.
//otherwise
Node* traversingNode = node->leftChild;
This is code that's inside a member function of the BinarySearchTree template. When a symbol, such as Node gets used the compiler needs to know what in blazes is that. BinarySearchTree defines an inner class named Node, so there you go. Problem solved.
template<typename T>
Node* ...
But what the heck is this? What is this weird Node all about? This part of the C++ code is not inside a member function. You better have a global class, or something, named Node, or you'll be in big trouble.
Just because there happens to be some class or template that's defined, and it has an inner class named Node, well this means absolutely nothing, whatsoever. When some symbol name is used, in global scope, the compiler is not going to search every class for something that happens to have the same name. C++ does not work this way.
And that's why you must spell everything out:
template<typename T>
typename BinarySearchTree<T>::Node *
The "template<typename T>" stuff makes a grandiose entrance of a template parameter that's represented by symbol T, and BinarySearchTree<T>::Node spells everything out.
And the second part of this story, the only remaining question here, is what in blazes is that typename all about.
Well, that's a long story, that you can read by yourself.
Boost documentation and previous stack overflow both give working examples of how to define custom comparator functions and include handle in the node type of a boost heap. However when I combine both of these features (a custom defined compare function and a handle within the node type) I get errors reporting invalid use of incomplete type of 'struct compare_Node'.
https://www.boost.org/doc/libs/1_63_0/doc/html/heap/concepts.html#heap.concepts.mutability
Using boost fibonacci_heap
Defining compare function for fibonacci heap in boost
Decrease operation in fibonacci heap, boost
Other than predefining both structs of Node and compare_Node I'm not sure to solve the circularity while still holding the handle's safely as a member within the Node struct.
#include <boost/heap/fibonacci_heap.hpp>
struct compare_Node; //predefine to avoid circular issues
struct Node; //predefine to avoid circular issues
using fib_heap = boost::heap::fibonacci_heap<struct Node*,
boost::heap::compare<struct compare_Node>>;
// 6-byte struct total
struct Node {
double value;
fib_heap::handle_type* handle; // orig
};
// override for min_heap
struct compare_Node
{
bool operator() (struct Node* const n1, struct Node* const n2) const
{
return n1->value > n2->value;
}
};
int main() {
fib_heap heap;
return 0;
}
Define compare_Node only with the declaration of operator(). Pointers to Node don't need Node definition. After Node definition, you can add the body of operator():
struct compare_Node
{
bool operator() (struct Node* const n1, struct Node* const n2) const;
};
using fib_heap = boost::heap::fibonacci_heap<struct Node*,
boost::heap::compare<struct compare_Node>>;
// 6-byte struct total
struct Node {
double value;
fib_heap::handle_type* handle; // orig
};
bool compare_Node::operator() (struct Node* const n1, struct Node* const n2) const
{
return n1->value > n2->value;
}
Online demo.
I'm kind of new at C++, so bear with me if you can. I'm trying to sort a vector full of nodes. In my .h file I have the following definition for a node:
class Node{
public:
Node(int data);
bool sortMe(const Node & n1, const Node & n2);
int getData();
private:
int nData;
};
In my .cpp file, I define the functions such as:
Node::Node(int data){
this->nData = data;
}
bool Node::sortMe(const Node & n1, const Node & n2){
return n1.nData < n2.nData;
}
and in main attempt to sort a vector with:
Node aNode(7);
Node bNode(90);
Node cNode(84);
std::vector<Node> arrayName;
arrayName.push_back(aNode);
arrayName.push_back(bNode);
arrayName.insert(arrayName.begin(), cNode);
std::sort(arrayName.begin(), arrayName.end(), &Node::sortMe);
I include algorithm and everything, I just can't figure out why it doesn't want to use that function to sort the data...
Thanks in advance!
sortMe() is currently declared as a member function. That means it needs to be called on a specific instance of the Node class, rather than being used as a standalone function.
To fix it, simply prefix the function declaration with static (only in the class header; not in the implementation). That means the function belongs to the class, not a specific instance.
You can use boost::bind:
std::sort( arrayName.begin(), arrayName.end(),
boost::bind(&Node::sortMe, this,_1,_2));
or make sortMe function static.
Even better is to use a functor instead of a function (this will be faster):
class Node{
public:
Node(int data);
bool sortMe(const Node & n1, const Node & n2);
int getData();
struct doCompare
{
bool operator()( const Node& n1, const Node& n2 )
{
// comparison code
}
};
private:
int nData;
};
std::sort( arrayName.begin(), arrayName.end(), Node::doCompare() );
The std::sort() need a reference of comparison function.
There will be two ways to implement the comparison function:
static member function
A normal member function shall not be used since a member function must need a specific instance of its class.
class Node{
public:
static bool sortMe(const Node & n1, const Node & n2);
};
normal function().
Remove the 'bool sortMe(const Node & n1, const Node & n2);' out from the Node class to the main.cpp, the problem will be solved.
bool Node::sortMe(const Node & n1, const Node & n2){
return n1.nData < n2.nData;
}
If you use C++11, you can use lambda.
std::sort(arrayName.begin(), arrayName.end(), [](Node& l, Node& r){ return l.getData() < r.getData(); });
I have the following class declaration (I've tried to remove as much excess code as possible):
class List {
public:
struct Node {
int value;
};
Node * findNode(unsigned int) {
return new Node;
}
};
This gives no error. However, as soon as I define the function "findNode" outside of the class, I get an error; here's the code:
class List {
public:
struct Node {
int value;
};
Node * findNode(unsigned int);
};
Node * List::findNode(unsigned int index) {
return new Node;
}
Now, when running the code, I get an error saying "LinkedList.cpp:9:1: error: 'Node' does not name a type".
I would appreciate any help in determining the problem.
Until the compiler encounters List:: it has no idea the Node you're talking about is a member of List. Change the definition to:
List::Node * List::findNode(unsigned int index) {
return new Node;
}
The "naked" Node inside the function is fine because by that time the compiler knows the function is a member of List.
I compiled the following cords with g++
#include <iostream>
#include <string>
using namespace std;
template<class T>
class Node<const char*>{
private:
string x_;
Node* next_;
public:
Node (const char* k, Node* next):next_(next),x_(k){}
string data(){return x_;}
Node *get_next(){return next_;}
};
$ g++ -c node01.cc
node01.cc:5: error: ‘Node’ is not a template
What's wrong?
I'm begginer for c++
You're mixing up declarations and instantiations. When you declare a template, you don't specify a type immediately after its name. Instead, declare it like this:
template<class T>
class Node {
private:
const T x_;
Node *next_;
public:
Node (const T& k, Node *next) : x_(k), next_(next) { }
const T& data(){return x_;}
Node *get_next(){return next_;}
};
Your original declaration also confuses string, const char *, and generic types that should be in terms of T. For a template like this, you probably want to let the user define the type of the member (x_). If you explicitly declare it as const char * or string, you're losing genericity by limiting what the user can use for T.
Notice that I changed the types of the instance variables, the parameters of the constructor and the return type of data() to be in terms of T, too.
When you actually instantiate a variable of the template type, you can provide a concrete type parameter, e.g.:
int main(int argc, const char **argv) {
Node<char*> *tail = new Node<char*>("tail", NULL);
Node<char*> *node = new Node<char*>("node", tail);
// do stuff to mynode and mytail
}
Whenever you write the template name Node outside the template declaration, it's not complete until you provide a value for the parameter T. If you just say Node, the compiler won't know what kind of node you wanted.
The above is a little verbose, so you might also simplify it with a typedef when you actually use it:
typedef Node<char*> StringNode;
int main(int argc, const char **argv) {
StringNode *tail = new StringNode("tail", NULL);
StringNode *node = new StringNode("node", tail);
// do stuff to mynode and mytail
}
Now you've built a linked list of two nodes. You can print out all the values in the list with something like this:
for (StringNode *n = node; n; n = n->get_next()) {
cout << n->data() << endl;
}
If all goes well, this will print out:
node
tail
Your class declaration should look like this:
template<class T>
class Node{
private:
T x_;
Node* next_;
public:
Node (const T& k, Node* next):next_(next),x_(k){}
T data(){return x_;}
Node *get_next(){return next_;}
};
Notice how I removed all references to string or const char * and replaced them with the generic type T. Your class, since it is templated, should not refer to any specific type but should do everything in terms of the generic T type.
The const char * is specified later when you declare a Node variable. Or it could be any other type, not just const char *. The point is, when you're declaring the Node class you just use the generic type T in the code without reference to any specific type. You specify a specific type only when you actually use a Node.
Node<const char *> stringNode("foo", NULL);
Node<int> intNode(5, NULL);
This has allowed us to have a single definition of the Node class but be able to use it to create both nodes where the data is a string and nodes where the data is an integer. Hooray templating!