why does the compiler declare a class method deleted? - c++

i'm trying to make a class which include std::pair container, see the code bellow.
why did the compiler declare a class method deleted?
how to fix this issue?
template <typename Kty_, typename Dty_>
class TreeNode {
public:
// tags:
using usI = unsigned short int;
using value_type = std::pair<const Kty_, Dty_>;
using pointer = value_type*;
using reference = value_type&;
using const_reference = const value_type&;
TreeNode(
const_reference pairValue,
usI height = 0,
TreeNode<const Kty_, Dty_> *parent = nullptr,
TreeNode<const Kty_, Dty_> *left = nullptr,
TreeNode<const Kty_, Dty_> *right = nullptr
) {
left_ = left;
parent_ = parent;
right_ = right;
pairValue_ = pairValue; // 48 // Overload resolution selected deleted operator '=' ​clang:ovl_deleted_oper
height_ = height;
}
protected:
TreeNode<const Kty_, Dty_> *left_;
TreeNode<const Kty_, Dty_> *parent_;
TreeNode<const Kty_, Dty_> *right_;
value_type pairValue_;
usI height_;
};
there is a set of examples which call this issue:
Example: Uninitialized data members: it doesn't work for me because i don't know how to initialize Kty_ & Dty_ by their default values
Example: Reference and const data members: i have tried to remove some of const keyword specifies, but it doesn't help
Example: Movable deletes implicit copy: not my case i think
Example: Indirect base members deleted: not my case i think
Example: Variant and volatile members: not my case i think

why did the compiler declare a class method deleted?
Because const members cannot be assigned to, value_type pairValue_; contains a const member.
how to fix this issue?
Initialize const members properly.
One cannot assign to constant members in the constructor's body, which is what you were doing, just move the "initialization" (or rather all of them) to the initializer list.
TreeNode(const_reference pairValue, usI height = 0,
TreeNode<const Kty_, Dty_> *parent = nullptr,
TreeNode<const Kty_, Dty_> *left = nullptr,
TreeNode<const Kty_, Dty_> *right = nullptr)
: left_(left),
parent_(parent),
right_(right),
pairValue_(pairValue),
height_(height) {}

Related

Assigning a variable using a class method within the constructor of a structure

I have a class called hash_t. The class contains a struct called node_t, with its respective constructor.
struct node_t
{ node_t *next;
string key;
TYPE data;
node_t(string _key, TYPE &_data)
{ next = nullptr;
data = _data;
key = _key;
}
};
Using a hash_t method shown below, we take the key, pass it to mkHash and return a hashed version of the key.:
uint64_t mkHash(const string &strng)
{ const unsigned char *str = (const unsigned char*)(strng.c_str());
unsigned char ch;
uint64_t rslt = 5123;
while ((ch=*str++) != '\0')
rslt = rslt * 33 + ch;
return rslt;
}
Basically what I'm trying to do, is change the node_t class to create a hash in it's constructor, to compare hash values instead of the keys, as this should use less comparisons. My thought process was to run the mkHash method inside of the constructor to assign a hash to node_t as such:
struct node_t
{ node_t *next;
string key;
TYPE data;
uint64_t hsh;
node_t(string _key, TYPE &_data)
{ next = nullptr;
data = _data;
key = _key;
hsh = mkHash(key);
}
};
And I'm getting this from MinGW:
error: cannot call member function 'uint64_t hash_t<TYPE>::mkHash(const string&) [with TYPE = std::__cxx11::basic_string<char>; uint64_t = long long unsigned int; std::__cxx11::string = std::__cxx11::basic_string<char>]' without object
How do I get the constructor of node_t to accept the method call for assignment? I'm not sure what's going wrong, or how to fix it, and any help is greatly appreciated.
Feeling incredibly silly at this one, I've worked it out. Changed the declaration of mkHash to be static and actually used the correct scope for the hash_t method:
struct node_t
{ node_t *next;
string key;
TYPE data;
uint64_t hsh;
node_t(string _key, TYPE &_data)
{ next = nullptr;
data = _data;
key = _key;
hsh = hash_t::mkHash(key);
}
};
Thank you for the contributions

Can I set default arguments for C++ functions that are union

As you can see in the following code, I attempt to have some default arguments of the function "initialize" that are union. How to change the definition of the function "initialize" to make it compatible with C++ before C++ 11? Do I need to add some constructors to RedBlackPointer? If so, how?
template <typename T> class RedBlackNode{
protected:
union RedBlackPointer{
RedBlackNode *node;
struct{
unsigned value:1; // for color / other info
}flag;
}left, right, parent;
T key;
public:
void initialize(T key, RedBlackPointer left = {(RedBlackNode*)0},
RedBlackPointer right = {(RedBlackNode*)0},
RedBlackPointer parent = {(RedBlackNode*)0}){
this->key = key;
this->left = left; this->right = right;
this->parent = parent;
}
}
Indeed, the extended initialization lists are not available before C++11.
As long as you keep in mind that only ONE member in a union can be active at any time, you can easily solve the issue with a default constructor:
template <typename T> class RedBlackNode{
protected:
union RedBlackPointer{
RedBlackPointer() : node(0) { } // <==== default constructor
RedBlackNode *node;
struct{
unsigned value:1; // for color / other info
}flag;
}left, right, parent;
T key;
public:
void initialize(T key, RedBlackPointer left = RedBlackPointer(), //refer to default ctor
RedBlackPointer right = RedBlackPointer(),
RedBlackPointer parent = RedBlackPointer()){
this->key = key;
this->left = left; this->right = right;
this->parent = parent;
}
void show() {
cout<<left.node<<","<<right.node<<","<<parent.node<<","<<key<<endl;
}
}; // <=== ;
And here how to demonstrate that it works:
RedBlackNode<int> N;
N.initialize(5);
N.show();
Here a live demo and here with a compiler that rejected your initial code.
Additional comment:
One thing puzzles me: in your union you combine a pointer with a one bit flag.
This is not shoking per se: it could imagine it being a trick to avoid overhead of pointer allocation, when sometimes the value poitned to is small enough to be stored directly in the tree.
However in this case, it's not clear how you will know wich is the active member (i.e. when to use the pointer, and when to use the flag is used).
So I'd suggest you cross check that there is not a mistake / forgottoen element here.

move semantics and unique_ptr

How would you perform a move operation on a class that uses unique_ptr? Wouldn't setting the unique_ptr to null cause deletion of the data? If I perform a copy through a list initializer of the unique_ptr like so, would the data be preserved or deleted?
template<typename T, typename A = std::allocator<T>>
class forward_list
{
...
private:
struct node
{
T data;
std::unique_ptr<T> next;
};
std::unique_ptr<node> root_;
std::unique_ptr<node> leaf_;
size_t count_;
const A& heap;
};
// Move constructor. Constructs the container with the contents of other using move semantics.
// If alloc is not provided, allocator is obtained by move-construction from the allocator belonging to other.
inline forward_list(forward_list&& other)
: root_(other.root_), leaf_(other.leaf_), count_(other.count_), heap(other.heap)
{
other.root_ = nullptr;
other.leaf_ = nullptr;
other.count_ = 0;
};
You need to move the pointer.
forward_list(forward_list&& other) :
root_(std::move(other.root_)),
leaf_(std::move(other.leaf_)),
count_(other.count_),
heap(other.heap)
{
// Do nothing
}

invalid use of non-static member C++98

I'm writing a C++ program that, unfortunately, requires the use of a C++98 compiler. After writing the program and trying to compile I get this error:
error: invalid use of non-static data member 'graph::adj_list'
This is confusing to me since I used cppreference (http://en.cppreference.com/w/cpp/language/data_members) to make sure this would compile. Can anybody help me out?
graph_frame.h
#include <cstddef>
class node{
friend class graph;
private:
int node_name;
int edge_weight;
node *next_cell = NULL;
node *previous_cell = NULL;
public:
node(int name = 0, int new_edge = 0);
~node();
};
class graph{
private:
void recursive_delete(int i, int k);
node** adj_list; <----------------ERROR
public:
//----argument not needed for constructor because a list is not created
//----until create_graph() is called
graph();
~graph();
//----remember to free all buckets from list
void create_graph(int& graph_nodes);
int check_node(int& source_node, int& dest_node);
void insert_node(int& source_node, int& dest_node, int& weight);
void print(node **dummy = adj_list, int i = 0, int k = 0);
void delete_node(int& source_node, int& dest_node);
};
node *next_cell = NULL;
node *previous_cell = NULL;
That won't fly - in-class initializers for non-static members were only introduced in C++11.
About adj_list, the real location of the error is here:
void print(node **dummy = adj_list, int i = 0, int k = 0);
// ^^^^^^^^^^
You can't have a class member as a default value because it's not known to which instance it should belong. You can't use this there either, so you'll have to figure out some other way to pass a default value.

How do I initialize a pointer in a struct to null in C++11?

Here's my struct:
struct node {
int load;
int tolerance;
bool has_fired;
node *in[1];
node *out[1];
};
I've tried:
node mynode;
mynode->in = null;
mynode->in = nullptr;
mynode->in = &nullptr;
mynode->in = 0;
mynode->in = false;
I really don't know what's wrong, I remember the first assignment USED to work but not anymore apparently. Any help?
EDIT: In the actual source file 'mynode' is a pointer inside of another struct.
Like this perhaps:
struct node
{
int load;
int tolerance;
bool has_fired;
node *in[1] = { nullptr };
node *out[1] = { nullptr };
};
(Note that node::in and node::out are arrays of pointers.)
Usage:
node n; // n.in and n.out are initialized
In C++11 the brace-or-equal-initializer makes the class a non-aggregate. If that's a problem, you can also omit the initializer and say:
node n;
n.in[0] = nullptr;
n.out[0] = nullptr;
Or even:
node n { 0, 0, false, { nullptr }, { nullptr } };
Try value initialization:
node mynode{};
This will value-initialize all the members, which for built-ins and PODS means zero initializaiton.
Create a constructor?
struct node
{
node()
: in{{ nullptr }}, out{{ nullptr }}
{}
...
};
This is assignment rather than initialization. Since in is an array of pointers you have to set the array element to null. Also mynode is not a pointer, so you don't use the arrow operator.
mynode.in[0] = nullptr;