C++ How to initialize a struct through no argument constructor - c++

Node is a struct which defined in a class List_set private.
struct List_set::Node
{
element_t str_l;
link_t next_ptr ;
static link_t* find(link_t* current, element_t string_t);
Node();
};
List_set::List_set():link_(nullptr)
{}
List_set::Node::Node():next_ptr{0}
{}
I want to use a constructor to initialize the Node, however the compiler always report an error:
no matching constructor for initialization of 'list_set::List_set::Node'
Can you please help to figure it out?
The next is the definition of class List_set hope it can provide some reference.
class List_set
{
public:
using element_t = std::string;
List_set();
List_set(std::initializer_list<element_t>);
bool is_empty() const;
size_t size() const;
bool contains(const element_t&) const;
void insert(element_t);
private:
struct Node;
using link_t = std::shared_ptr<Node>;
link_t link_;
};

Related

C++ : How to create a copy constructor of array that has a pointer?

I have
template <class T>
class arrList: public linearList<T> {
public:
arrList() {}
arrList(const arrList<T>& List);
~arrList() {delete[] element; }
protected:
void indexCheck(int indx) const;
T* element;
int arrLength;
int listSize;
};
And the copy constructor is
template<class T>
inline arrList<T>::arrList(const arrList<T>& List) {
element = List.element;
arrLength = List.arrLength;
listSize = List.listSize;
}
But im not sure if this is correct for T* element, and also if I have to insert the void function in the copy constructor too.
I am new to this, and I don't know a lot about it, so any kind of help will be appreciated.

Creating inline function in header class to a private variable

I have to make a linked list. I'm not sure if I'm doing this right first of all. But basically the project says I'm not allowed to make a .cpp file but I have to create 4 inline statements through the .h file.
class Queue{
private:
struct QueueNode{
int size;
std::string party;
QueueNode *next;
};
QueueNode *front;
QueueNode *rear;
public:
// Constructor
Queue();
// Destructor
~Queue();
// Queue operations
std::string getPartyName() const { return party; } // This and next 3 lines give error with the private variables
int getSize() const { return size; }
void setPartyName(std::string p) const{ party = p; }
void setSize(int s) const{ size = s; }
};
You are halfway there. You need to declare the functions in the header file, as you have done.
The missing step is that you need to not define the functions within the class body but instead define them below the class declaration using the class name with the scope resolution operator and the inline operator.
The other piece you are missing is that you are declaring functions in your Queue class that are likely meant for your QueueNode struct.
class Queue{
private:
struct QueueNode{
int size;
std::string party;
QueueNode *next;
};
QueueNode *front;
QueueNode *rear;
public:
// Constructor
Queue();
// Destructor
~Queue();
// Queue operations
std::string getPartyName( const QueueNode * const node ) const;
int getSize( const QueueNode * const node ) const;
void setPartyName( QueueNode & out_node, std::string & p);
void setSize( QueueNode & out_node, int s);
};
inline std::string Queue::getPartyName( const QueueNode * const node ) const
{
return node->party;
}
inline int getSize( const QueueNode * const node ) const {
return node->size;
}
inline void Queue::setPartyName( QueueNode & out_node, std::string & p) {
out_node.party = p;
}
inline void Queue::setSize( QueueNode & out_node, int s) {
out_node.size = s;
}
It isn't clear what nodes you intend to set these values for, so I'll fill in the functions with some assumptions.
Either way I think you get the point. If you want to define inline functions within a header class, you cannot define the body within the class itself. You must declare it inline, which is a compiler suggestion, outside the body of the class. I know I didn't complete define the functionality of a linked list, I will leave that to you. But, this should answer the inline question.

Returning a non-const reference causes a binding reference error

I've implemented a double linked list using weak and smart pointers. The program is working but I have doubts about that const in the getPrev signature method. If I put const a the end of the method signature it will cause a binding reference error
error: binding reference of type 'std::weak_ptr<Node<Integer> >&' to 'const std::weak_ptr<Node<Integer> >' discards qualifiers
return prev;
Wasn't the purpose of that const to mark *this as const ? The return type is non-const for my understanding.
Here is the code, main.cpp:
#include <memory>
#include <iostream>
#include "DoubleLinkedList.h"
class Integer {
private:
int number;
public:
Integer(int number) : number(number) {}
int get() { return number; }
};
int main() {
DoubleLinkedList<Integer> list;
list.insert(Integer(1));
list.insert(Integer(2));
list.insert(Integer(3));
list.insert(Integer(4));
list.insert(Integer(5));
return 0;
}
DoubleLinkedList.h
#include <memory>
#include <vector>
#include <iostream>
template <typename T>
class Node {
private:
T data;
std::weak_ptr<Node> prev;
std::shared_ptr<Node> next;
public:
Node(): data(0) {}
Node(const T &object) : data(object) {};
T getData() const {
return data;
}
void setData(T data) {
Node::data = data;
}
std::weak_ptr<Node> &getPrev() const {
return prev;
}
void setPrev(const std::weak_ptr<Node> &prev) {
Node::prev = prev;
}
std::shared_ptr<Node> &getNext() {
return next;
}
void setNext(const std::shared_ptr<Node> &next) {
Node::next = next;
}
};
template <typename T>
class DoubleLinkedList {
private:
std::shared_ptr<Node<T>> header;
std::weak_ptr<Node<T>> trailer;
int size;
public:
DoubleLinkedList() : size(0) {}
void insert(const T &value) {
auto node = std::make_shared<Node<T>>(value);
if (size++ == 0) {
header = node;
} else {
auto last = trailer.lock();
last->getNext() = node;
node->getPrev() = last;
}
trailer = node;
}
};
If you are inside a const method, all the data members are considered const.
That is, inside this function:
std::weak_ptr<Node> &getPrev() const
you can imagine the member variables like this:
const T data;
const std::weak_ptr<Node> prev;
const std::shared_ptr<Node> next;
It should be clear that you cannot return a non-const reference to a const object:
const int x;
int& getX()
{
return x; // error
}
The reference would allow you to modify x even though it is const, so this is forbidden (formally: a non-const reference cannot bind to a const object).
Inside a const member function of Node, prev is a const std::weak_ptr<Node>, so a std::weak_ptr<Node>& cannot bind to it for the exact same reason.
It appears that within insert you do intend to modify node (by changing its prev value), in which case the getPrev function should not be const (because you intend to modify the object). But this kind of access should probably be reserved for the DoubleLinkedList and not some arbitrary outside user. It then becomes a question of interface design: Which parts of your code are implementation details and how those should be hidden from users? Which parts are the interface that users should interact with (with minimal opportunity for breaking things)?

Why can't I insert a const pointer to a multiset?

According to the documentation for multiset for instance see http://www.cplusplus.com/reference/set/multiset/insert/. It should be possible to insert a const value. In my example the multiset is a collection of pointers, but when I try to insert a const pointer I get an error.
template<typename Key>
struct node_key: public node_base {
node_key(Key k): _key(k) {}
virtual ~node_key() {}
const Key& key() const { return _key;}
protected:
Key _key;
void _copy_key(node_key<Key> *n) const { n->_key=_key;}
};
template <typename Compare>
struct ptr_less_key {
ptr_less_key() : _comp() {}
virtual ~ptr_less_key() {}
template <typename Pointer>
bool operator()(const Pointer& a, const Pointer& b) const { return _comp(a->key(), b->key()); }
Compare _comp;
};
int main() {
typedef node_key<int>* keyp;
std::multiset<keyp,ptr_less_key<std::less<int>>> x;
node_key<int> k(5);
const node_key<int> *p=&k;
x.insert(p); //this fails
return 0;
}
What you are currently doing: You are not trying to insert a const pointer, as you think you do, but a non-const pointer to a const element.
Change this
const node_key<int> *p=&k;
to this
node_key<int> *const p=&k;
to make the const keyword apply on the pointer rather than on what it points to.
Given
struct node {
void member();
void const_member() const;
};
consider the four declarations
node* pointer_to_node;
const node* pointer_to_const_node;
node* const const_pointer_to_node;
const node* const const_pointer_to_const_node;
There are two different aspects of constness: that of the object node and that of the pointer. The first two declare mutable pointers to either node or const node. A conversion from node* to const node* is allowed (and implicit), but not the other way around, as this would allow to modify a const node.
The second two declarations declare the respective pointers to be constant, i.e. these pointers cannot be modified (though the node pointed to by const_pointer_to_node can.
pointer_to_node->member(); // okay
pointer_to_node->const_member(); // okay
pointer_to_node = new node; // okay
pointer_to_node = const_pointer_to_node; // okay
pointer_to_node = pointer_to_const_node; // ERROR
pointer_to_const_node->member(); // ERROR
pointer_to_const_node->const_member(); // okay
pointer_to_const_node = new node; // okay
pointer_to_const_node = pointer_to_node; // okay
pointer_to_const_node = const_pointer_to_node; // okay
pointer_to_const_node = const_pointer_to_const_node; // okay
const_pointer_to_node->member(); // okay
const_pointer_to_node->const_member(); // okay
const_pointer_to_node = new node; // ERROR
const_pointer_to_node = const_pointer_to_node; // ERROR
const_pointer_to_node = pointer_to_const_node; // ERROR
const_pointer_to_const_node->member(); // ERROR
const_pointer_to_const_node->const_member(); // okay
const_pointer_to_const_node = new node; // ERROR
const_pointer_to_const_node = const_pointer_to_node; // ERROR
const_pointer_to_const_node = pointer_to_const_node; // ERROR

Doubly Linked List node's next is private

I'm implementing a doubly linked list and I'm using an object of my own as the data being stored.
Here is my object:
#ifndef PLAY_H_INCLUDED
#define PLAY_H_INCLUDED
#include <string>
class Play
{
private:
int m_quarter;
int m_minutes;
std::string oTeam;
std::string dTeam;
int m_down;
int m_yardToGO;
int m_startLoc;
int playDesc;
std::string wholePlay;
int relevance;
int relCounter;
public:
int getQuarter();
int getMinutes();
std::string getoTeam();
std::string getdTeam();
int getDown();
int getYard();
int getStartLoc();
int getPlayDesc();
std::string getwholePlay();
Play(int quarter, int minutes, std::string offense, std::string defense, int dwn, int ytg, int start, int desc, std::string play, int relevance, int relCounter);
~Play();
Play parse(std::string toParse);
std::string findPlay(std::string playDesc);
};
#endif // PLAY_H_INCLUDED
-
Here is my node:
template<class T>
class node{
friend class Play;
T data;
node *next, *prev;
node(const T& t, node *n = 0, node *p = 0) {data=t; next=n; prev=p;}
};
The exact error I get is:
error: node<Play>* node<Play>::next is private.
I assume I get this problem because Play's information is private and inaccessible to node, and to fix this I tried making node a friend class of Play. When I did that I get errors saying "node is not a template type". The error makes no sense to me so I assume this isn't the way to correct my problem.
Thanks.
Use public: above properties which should be public. If you don't specify anything, everything becomes private.
template<class T>
class node{
public: // ADD THIS
friend class Play;
T data;
node<T> *next, *prev;
node(const T& t, node<T> *n = 0, node<T> *p = 0) { // EDIT
data=t; next=n; prev=p;
}
};
Edit: You always need use <> when using template classes, like I edited in above.
All attributes in a class are private by default. Make it a struct instead or add public: at the beginning.
But I guess that is not the problem. When using node *next, *prev;, use this instead:
typedef typename node<T>* MyType;
MyType *next, *prev;