Compiler error in default parameters in class - c++

I'm trying to pass the second argument optional to my search function:
class ExponentialTree
{
public:
node* Search(int num, node* curr_node=root);
void Insert(int num);
private:
node* root;
};
node* ExponentialTree::Search(int num, node* curr_node)
{
If I call with one parameter, I want it to set it to root. I tried defult parameter in declaration, default parameter in implementation, both(I know its not true), two declaration. Nothing worked. Any ideas? I don't want overloading method beacuse it is the only line that will change.
Thanks.

Use:
node* Search(int num, node* curr_node=NULL);
and handle the case of NULL pointer in the body of the function:
node* Search(int num, node* curr_node)
{
if (curr_node == NULL){
//...
}
//...
}
Or it can be set in the implementation part too, but just with NULL.

A non-static member variable can not be used as a default argument.
Below is the relevant section in C++ standard draft (N3225), section § 8.3.6, point 9:
.. a non-static member shall not be used in a default argument expression, even if it
is not evaluated, unless it appears as the id-expression of a class member access expression (5.2.5) or unless
it is used to form a pointer to member (5.3.1). [ Example: the declaration of X::mem1() in the following
example is ill-formed because no object is supplied for the non-static member X::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a); // error: non-static member a
// used as default argument
int mem2(int i = b); // OK; use X::b
static int b;
};
root is a non-static member variable here -- hence you can not specify it as a default argument.

This is a classic example of where you actually would gain from using an overload:
node* Search(int num, node* curr_node)
{
// Your implementation
}
and then
inline node* Search(int num) { return Search(num, root); }
Hereby you explicitly state, that when no parameter is given, you should use root as the value for curr_node.
There is no need to make a runtime test, when the code can be decided at compile time, and you don't have to write NULL when you actually mean root.

Related

Return value type does not match the function type CONST

Not sure why error is happening on this function when I made the variable length const on a different function
int list::length() const {
return length;
}
CPP File Above
Header file BELOW
class list {
private:
struct Node
{
int info;
Node *next;
};
int length;
Node *head;
public:
list();
list(const list& otherlist);
~list();
int list::length() const;
};
The first issue is that you are qualifying length() inside your class. Remove list::. The second issue is that your member variable length, and your member function length are conflicting, because they have the same name.
I'd rename your members so that they don't clash with the functions. Consider length_ and head_.
Edit: please also post compiler errors in the future, as it makes other readers' jobs a little easier :)

Invalid use of non-static data member while using templates

I have the following code snipped, which implements a Binary Search Tree with templates:
#include<iostream>
using namespace std;
template<typename T>
class Node{
public:
T data;
Node<T> *left;
Node<T> *right;
Node<T> *parent;
Node(T input_data=NULL){
data=input_data;
left=NULL;
right=NULL;
parent =NULL;
}
};
template<typename T>
class BinarySearchTree{
private:
long n;
Node<T> *root;
public:
BinarySearchTree(Node<T> *input_root=NULL, long input_size=0){
n=input_size;
root=input_root;
}
void insert(Node<T> *p=root, T data){
Node<T> *par=NULL;
while(p!=NULL){
par=p;
if(data <= p->data)
p=p->left;
else
p=p->right;
}
Node<T> *z=new Node<T>(data);
if(root==NULL){
root=z;
n=1;
return;
}
z->parent=par;
if(data<=par->data)
par->left=z;
else
par->right=z;
n+=1;
}
void inorder(Node<T> *p=root){
if(p){
inorder(p->left);
cout<<p->data<<" ";
inorder(p->right);
}
}
int main(){
BinarySearchTree<int> *t=new BinarySearchTree<int>();
t->insert(5);
t->insert(15);
t->insert(3);
t->insert(14);
t->insert(25);
t->insert(10);
t->inorder();
}
There's a compilation error on line 27, (i.e. Node *root;), and which reads: "Invalid use of non-static data member 'BinarySearchTree::root'". I think it has to do with the default arguments that I've included have in the functions 'insert' and 'inorder', because I don't get the error when I remove the default argument 'root'.
My question is, what is happening and how do I get around it? I would like to preserve the default argument of root if that's possible.
If it matters, I'm using a software called 'Quincy 2005' on Windows 8.1 to compile (for certain reasons).
A default value must be a literal, not a variable name.
Additionally, arguments with default values must come last in the argument list.
Rather use:
void insert(Node<T> *p, T data) { ... }
// overload with only one argument
void insert(T data)
{
insert(root, data)
}
In a line such as
void insert( Node<T>* p = root ,T data ) {...}
there are 2 errors.
Firstly ,you can only use default value for the arguments starting at the last parameter and backwards.
Since you didn't give data a default value ,this is an error (solution reorder parameters ,those without default must come first).
Secondly ,the value root is a member of this and there is no this at the point of declaration.
Solution if you need a default there use nullptr as the default and inside your function test for nullptr and if so use root instead.

Error C2512 No appropriate default constructor even though I have one?

Solved by added a default constructor to the symbol struct, but also I would like to ask why there is a call to a default constructor if possible. If not, it's fine. thanks.
I'm trying to write a tree, but when I define a node like so:
TreeNode<SymbolPriority>* treeRoot =
new TreeNode<SymbolPriority>(SymbolPriority('a', 1));
I can't compile and it throws an Error c2512 'SymbolPriority': no default appropriate default constructor; however, in my struct I have the constructor I am trying to use, and I have used it before, so I do not know what is going on.
I have tried this:
SymbolPriority aSymbol( 'a', 1 );
TreeNode<SymbolPriority>* treeRoot = new TreeNode<SymbolPriority> (aSymbol);
but it doesn't work either.
I put down the relevant code below:
template<typename DATA_TYPE> struct TreeNode
{
TreeNode(const DATA_TYPE& value, TreeNode* left = NULL, TreeNode* right = NULL)
{
Value = value;
Left = left;
Right = right;
}
DATA_TYPE Value;
TreeNode* Left;
TreeNode* Right;
bool IsLeaf() const
{
return Left == NULL && Right == NULL;
}
};
and
struct SymbolPriority
{
SymbolPriority(char aSymbol, int priority){
Symbol = aSymbol;
Priority = priority;
};
char Symbol;
int Priority;
bool operator > (const SymbolPriority& compareTo) const{
return (Priority > compareTo.Priority );
};
bool operator < (const SymbolPriority& compareTo) const{
return !( *this > compareTo);
};
bool operator==(const SymbolPriority& compareTo) const{
return (Priority == compareTo.Priority );
};
};
Default constructors are used to initialize objects without use of arguments.
To fix this, simply put:
TreeNode() { // NO PARAMETERS
... // default initializing variables, or whatever you'd like
}
In your structures, classes, and any others if they are declared without arguments.
In case you'd like to hear more on the concept of "Default Constructors".
There are quite a few stackoverflow questions relating to Error: C2512.
Consider looking at this:
error C2512: no appropriate default constructor available
Wikipedia happens to give a great explanation on the necessity of default constructors here.
Some notable purposes are:
"When an array of objects is declared, e.g. MyClass x[10];; or allocated dynamically, e.g. new MyClass [10]; the default constructor is used to initialize all the elements"
"When an object value is declared with no argument list, e.g. MyClass x;; or allocated dynamically with no argument list, e.g. new MyClass or new MyClass(); the default constructor is used to initialize the object"
"When a derived class constructor does not explicitly call the base class constructor in its initializer list, the default constructor for the base class is called"
That last one is important for inheritance.

Can I use a member element as the default argument for a method of the class?

The method Minimum returns the minimum element in the binary search tree. If no argument is passed it prints the minimum of calling object. If address of a node is passed it prints the minimum of the subtree whose root is node
When compiled it shows "Invalid use of non static data member Tree::root"
#include<stdlib.h>
#include<iostream>
class Node
{
public:
Node *leftchild;
Node *rightchild;
Node *parent;
int info;
};
class Tree
{
public:
Node *root;
Tree()
{
root=NULL;
}
void Minimum(Node*);
};
void Tree::Minimum(Node *curnode=root)
{
Node *parent;
while(curnode!=NULL)
{
parent=curnode;
curnode=curnode->leftchild;
}
std::cout<<parent->info<<endl;
}
int main()
{
Tree tree;
tree.Minimum();
return 0;
}
No, you cannot.
For the default value you can use either a value, a variable or a function that is accessible in the context of the function definition that is, in the class definition, which is outside of any particular object's context.
It usually helps me thinking on how the compiler really processes this. In particular, when the compiler does overload resolution for a function and finds an overload that has more arguments than those used at the place of call, the compiler will generate code at the place of call to fill in the rest of the arguments. The generated code will always generate a call with all of the arguments:
int g();
void f(int x = g());
int main() {
f(); // [1]
}
When the compiler processes [1] and it does overload resolution it finds that void ::f(int x = g()) is the best candidate and picks it up. It then fills the default argument and generates the call for you:
int main() {
f( /*compiler injected*/g() );
}
If you consider a call to a member function, or a member variable of the class, it would not make sense in the context of the caller (the language could be changed to adapt to this, it is not impossible to handle that, but with the current model it does not work).
You can alternatively set it to NULL for example as default, and then check and set it to the member in the method.
Or overload the method with void Minimum(); and in that method call the one with an argument with the member.
void Tree::Minimum() {
Minimum(root);
}
I couldn't find any way to get the default parameter to work like that. But you can get the same result by overloading the function, like so:
class Tree
{
public:
Node *root;
Tree()
{
root=NULL;
}
void Minimum(Node*);
void Minimum();
};
void Tree::Minimum(Node *curnode)
{
Node *parent;
while(curnode!=NULL)
{
parent=curnode;
curnode=curnode->leftchild;
}
std::cout<<parent->info<<std::endl;
}
void Tree::Minimum()
{
Minimum(root);
}
If the case where an argument of NULL is explicitly passed doesn't need to be differentiated from no argument being passed, you could set NULL as the default and use root if curnode is NULL.
void Tree::Minimum(Node *curnode=NULL)
{
if (curnode==NULL)
curnode = root;
Node *parent;
while(curnode!=NULL)
{
parent=curnode;
curnode=curnode->leftchild;
}
std::cout<<parent->info<<endl;
}

Template Class Linked List Insertion Error

When I attempt to insert this 'food' object into my template class linked list 'test'. I get this error:
request for member ‘addNode’ in ‘test’, which is of non-class type ‘Catalog<FoodSource>()
Here's my coding, What am I doing wrong?
##main:##
int main(void)
{
Catalog<FoodSource> test();
FoodSource food();
test.addNode(const &food);
return(0);
}
##function definition in .h:##
template<class T>
class Catalog
{
public:
void addNode(const T& value);
};
##function implementation in .cpp:##
template <class T>
void Catalog<T>::addNode(const T& value)
{
Node *temp;
if(head == NULL)
head = new Node (value, NULL);
else
{
temp=head;
while(temp->next !=NULL)
temp=temp->next;
temp->next = new Node (value, NULL);
}
}
You just found one of the many warts present in the C++ syntax. The standard requires that if an expression can be interpreted both as a declaration and as a definition then it must be considered as a declaration. For example your code
Catalog<FoodSource> test();
is not defining a variable named test but is instead declaring that there is a function named test that takes no arguments and that returns a Catalog<FoodSource> instance.
To define the variable you need to omit the parenthesis.
Note that there are cases where this trap is much harder to notice... for example:
double x = 3.14159;
int y(int(x));
as surprising it may seem in the above code y is declared as a function!
Declaration and implementation of a class template should be in the same file.
Also, you can just call test.addNode(food); in main.
Given definition for all the classes Node, FoodSource etc is available, you need to do at least the following:
1) Move the function definition to .h file
2) The first line in main function is ambigous. It should be rewritten as Catalog<FoodSource> test; because Catalog<FoodSource> test() will be treated as function prototype