use operators in templates in c++ - c++

I am trying to implement a List class using pointers and am trying to implement a function LOCATE(T x) where T is for the template and returns the first position of the element x if found, else returns last position + 1.
My functions code is
template<class T>
int List<T>::locate(T n) const
{
int size = end();
Node<T> * p = head_;
for (int i = 0; i < size; i++)
{
if (p->data() == n) // fails on this line
return i;
p = p->link();
}
return size; // if no match found
}
I initialise my list with T as string as
List<string> myList;
but I get an error message
'bool std::operator ==(const std::istreambuf_iterator<_Elem,_Traits> &,const std::istreambuf_iterator<_Elem,_Traits> &)' : could not deduce template argument for 'const std::istreambuf_iterator<_Elem,_Traits> &' from 'std::string
Why is the error coming up even though the '==' operator is defined for the string class?
'
The code for Node is
template<typename T>
class Node
{
public:
// Constructors
Node();
Node(T d, Node<T> * l = NULL);
//Inspectors
T data() const;
Node<T> * link() const;
// Mutators
void data(T d); // assigns new value to Node
void link(Node<T> * l); // points this Node to a different one
// Destructor
~Node();
private:
Node<T> * link_;
T data_;
};
template<typename T>
T Node<T>::data() const
{
return data_;
}
template<typename T>
Node<T>* Node<T>::link() const
{
return link_;
}
The calling code is
List<string> test;
test.add("abc");
cout << test.locate("abc") << endl;

Without getting neck-deep in your code, I notice several problems.
Firstly,
locate(T n)
should be
locate(const T& n)
This saves a possible copy of n
And to ask a stupid question, are you sure you've done:
#include <string>

Try :
if( n.compare(p->data()) == 0 )
string::compare documentation
As the comments below have noted, operator== should work. Please double check that you have
#include <string>
using std::string;

The reference to std::istreambuf_iterator is peculiar as nothing in the code you show justifies it -- can you please show us Node and whatever other code impinges on this in a minimal failing example? Trying to evince the problem from very partial code and an error message is very much like pulling teeth...!-)

This looks OK, I can't see how the std::istreambuf_iterator gets into the picture...
One thing you may want to adjust is taking const T& instead of T as in-parameters to your methods, e.g.
Node(const T& d, Node<T> * l = NULL);
void data(const T& d);
int List<T>::locate(const T& n) const { ...
What with the actual problem, there's bound to be something else going on.

Start deleting code untill it works again. Some typo or rogue macros or conflicting namespaces screw things up.
Will this compile by itself?
string data = "bla";
Node<string> p("bla");
bool b = p.data() == data;
(Every C++ programmer should make a cout << "bla" << end; typo. Very entertaining)

Related

Template demands Type and compiles anyway

I have been searching on stack overflow, in my textbook, and google and everywhere, for like 2 days now for to try and fix/understand this issue.
I am writing this code out of a book I bought and it looks right to me, and I have gotten the code to compile after misspelling 'appnd' and 'prepnd' on purpose, and using GNU compiler 10.2.1, but wanted to know why basically and see if I could make it also run on clang++ and not have the spelling error and all that.
Like I said, this code compiles on my computer with GNU, but also on compiler explorer it says there is an issue with the same compiler(the same issue).
So this error keeps coming up saying I cant make an append or prepend with no type when dude(Dmytro Kedyk) is using a template as the type.
And I know there is an std::append or whatever for strings, but i am not using std, so like what gives.
And if you look at the code he uses append before the line throwing the error, but it has no issue with append there.
I seems like it should work, and if I misspell 'append or prepend' it works on GNU. why is clang not playing nice, or am I not playing nice with clang?
error: ISO C++ forbids declaration of ‘append’ with no type [-fpermissive]
On this line
template<typename ARGUMENT> append(ARGUMENT const& a){
On the second line with the append I keep getting an error
Notes: This is not my code! This is just from a book I own.
transcribed with small changes and added notes from:
page 44 "Implementing Useful Algorithms in C++", by: Dmytro Kedyk
template <typename ITEM> class simpleDoublyLinkedList{ //template for item and class dec
struct Node{
ITEM item; //data
Node *next, *prev; //links to next and last
template<typename ARGUMENT> //tempalting for argument
Node(ARGUMENT const& a): item(a), next(0), prev(0) {} //creating node obj inside Node struct
} *root, *last; //pointers to next and last
void cut(Node* n){ //funct to unlink node, takes node *
assert(n); //assert on node object
(n == last ? last : n->next->prev) = n->prev; //
(n == root ? root : n->prev->next) = n->next; //
}
public:
simpleDoublyLinkedList(): root(0), last(0) {} //
template<typename ARGUMENT> append(ARGUMENT const& a){ //line throwing error
Node* n = new Node(a); //making new node 'with new'
n->prev = last; //add to end of list
if(last){last->next;} //move down list
last =n; //
if(root){root = n;} //if root is true make root n
}
class Iterator{
Node* current; //current node obj (like 'this' but not predefined)
public:
Iterator(Node* n): current(n){} // member taking node
typedef Node* Handle; //Handle pointer type made of node type
Handle getHandle(){return current;} //function to return current as handle
Iterator& operator++(){ //overloading ++ operator
assert(current);
current = current->next;
return* this;
};
Iterator& operator--(){ //overloading -- operator
assert(current);
assert(current);
current = current->prev;
return* this;
};
ITEM& operator* ()const{assert(current);return current->item;} //overloading *
ITEM& operator->()const{assert(current); return &current->item;} //overloading ->
bool operator==(Iterator const& rhs)const{return current == rhs.current;} //overloading ==
};
Iterator begin(){return Iterator(root);} //returing root from iterator
Iterator rBegin(){return Iterator(last);}
Iterator end(){return Iterator(0);}
Iterator rEnd(){return Iterator(0);}
void moveBefore(Iterator what, Iterator where){ //function to move items in list
assert(what != end()); //assert what is not end
if(what != where){ //omit self refrence
Node *n = what.getHandle(), *w = where.getHandle(); //
cut(n);
n->next = w;
if(w){
n->prev = w->prev;
w->prev = n;
}else{
n->prev = last;
last =n;
}
if(n->prev){n->prev->next = n;}
if(w == root){root= n;}
}
}
template<typename ARGUMENT> prepend(ARGUMENT const& a){ //other line throwing error
append(a);
moveBefore(rBegin(), begin());
}
void remove(Iterator what){
assert(what != end());
cut(what.getHandle());
delete what.getHandle();
}
simpleDoublyLinkedList (simpleDoublyLinkedList const& rhs){
for (Node* n = rhs.root; n; n=n->next){append(n->item);}}
simpleDoublyLinkedList &operator=(simpleDoublyLinkedList const&rhs){
return genericAssign(*this, rhs);}
~simpleDoublyLinkedList(){
while(root){
Node* toBeDeleted = root;
root = root->next;
delete toBeDeleted;
}
}
};
append and prepend are functions but he has not put a return type in front of them. I think those lines should have a void return type, like this
template<typename ARGUMENT> void append(ARGUMENT const& a){ //line throwing error
template<typename ARGUMENT> void prepend(ARGUMENT const& a){ //other line throwing error
Because they have no return type, the compiler is attempting to interpret the function name as the return type. It has not seen that type before (because it's not a type) so it complains that the "type" is undefined. (Well technically, if it actually does build, I guess it assumes a void return type and lets you get away with it but warns you)

operator == overload for double linked list

I have realized Double Linked List. And now i need to overload == operator.
dll.cpp:67:17: error: expected expression
if ([ind] != sp[ind]) {
The problem i don't understand how to overload == operator if only one parameter is given. I mean if i write bool operator ==(DLL sp1, DLL sp2){} compiler says error: overloaded 'operator==' must be a binary operator (has 3 parameters)
#include<iostream>
#include<string>
using namespace std;
template<typename T>
class DLL {
public:
DLL(){
size = 0;
head = nullptr;
tail = nullptr;
}
T operator [](int ind) {
int counter = 0;
T res = T();
Node *cur = this->head;
while(cur != nullptr) {
if(counter == ind) {
res = cur->data;
}
cur = cur->next;
counter++;
}
return res;
}
bool operator ==(DLL<int> sp){
bool isequal = true;
for(int ind = 0; ind < sp.length(); ind++){
if ([ind] != sp[ind]) {
isequal = false;
}
}
return isequal;
}
void clear() {
while(size != 1)
pop_front();
delete tail;
size--;
}
int length() {return size;}
}
private:
class Node{
public:
T data;
Node *next;
Node *prev;
Node(T data = T(), Node *prev= nullptr, Node *next = nullptr) {
this->data = data;
this->next = next;
this->prev = prev;
}
};
int size;
Node *head;
Node *tail;
};
The way you have it defined as a member function (and it only takes list of int for some reason (you should probably remove the <int>).
bool operator ==(DLL<int> sp); // There is a small issue in that you
// passing by value and thus causing a copy.
// Another issue with this is that it should
// probably marked "const" to indicate state
// is not changed by the call.
When the compiler see's this.
list1 == list2
This is simply syntactic sugar for:
list1.operator==(list2);
Thus is why you only need one parameter when you declare it as a member function. The alternative is to declare it as a friend function.
friend bool operator ==(DLL<T> const& lhs, DLL<T> const& rhs);
In this case it is a free standing function. When the compiler sees:
list1 == list2
This is syntactic sugar for:
operator==(list1, list2)
The problem was that you were defining a member function with two parameters. The left hand side is the class object and then you were expecting two objects on the right hand side (but the == operator only has one place on the right). That is why it is complaining about three parameters.
So the real question is should it be a member or a friend.
It does not matter here.
There are situations where it "can".
Example: If your class contains a single argument constructor (lets say you could create a list from an integer) and you use a member operator==()
DLL<int> list;
if (list == 5) {
}
This will now compile. Because your member operator uses a parameter and the compiler can convert an integer into the DLL parameter using a single argument constructor.
The counter argument to this is that normally you don't want automatic conversions of your type so you should mark single argument constructors as explicit to prevent this.
So:
If you class can automatically be created via a one argument constructor (most cases this is not true but it can be).
Then you should prefer a friend function version.
otherwise it does not matter and I would probably fall towards the member function.
You're doing the right thing for the most part.
The problem that is causing this error:
dll.cpp:67:17: error: expected expression if ([ind] != sp[ind]) {
is that you actually want to do this instead:
*this[ind] != sp[ind]
Also, there appears to be an extra } right here:
int length() {return size;}
} // <- not exactly sure what that's about, but I don't think you need it.
A comparison operator is a binary operator that treats both the operands equally, it is advisable to make it a friend function and not a member.
So the declaration for the function would change to
friend bool operator ==(const DLL<int> & lhs, const DLL<int> & rhs);
You can choose to define it inside or outside the class.
Read here on when you need to make an operator member vs non-member.

C++ operator overloading []

i have a little problem with my code in c++.. I need to doit this way, because it's work to school..
I have template named Catalog
template <typename T>
class Catalog
{
struct Item{
T* _product;
unsigned int _amount;
Item* _next = nullptr;
};
Item* _head;
Item* _actual;
Item* _last;
int _size;
void init()
{
this->_size = 0;
this->_head = nullptr;
this->_actual = nullptr;
};
public:
Catalog(void)
{
this->init();
};
T*& operator[](unsigned int){
Item* node = this->_head;
for (int i = 0; i < this->_size; i++)
{
if (i == pos)
{
return &node->_product;
}
node = node->_next;
}
return nullptr;
};
};
It's a structure where i have Items and in Items i have pointer to next one in array..
I tryed to like this
Catalog<Products> *catalog = new Catalog<Products>();
Products *pr1 = new ProductA(5, "jmeno", 5);
catalog->Add(pr1, 5);
Products* ct = catalog[0];
In my case visual studio is reporting this error
IntelliSense: no suitable conversion function from SemestralniPrace::Catalog<Products>" to "Products *" exists
I want to correct operator[] so i can use my catalog like i need to.. or correct the code in main..
It's for example, i have some more functions in class Catalog, but it isn't importnent for this problem..
Can someone help me please.. Even suggestions is good for me. I am desperate with this.
Thanks and sorry for my English, it's not mine native language.
You have two mistakes. The first one is relative to the return statement of the operator []. The type of expression &node->_product is T** while the return type of the operator is T*&
You have to write simply
return node->_product;
The second mistake is relative to statement
Products* ct = catalog[0];
You have to write either
Products* ct = ( *catalog )[0];
or
Products* ct = catalog[0][0];

No Match for 'operator' error in C++

#include <iostream>
#include <string>
#include <cstdlib>
#include <cassert>
#include <ctime>
#include <map>
using namespace std;
struct SBLnode {
string name;
SBLnode *next;
SBLnode * left, * right;
};
struct Queue {
SBLnode * first, * last;
};
typedef SBLnode* BST;
struct SBL {
Queue q;
BST root;
};
void SBL_init (SBL& sbl) {
sbl = NULL;
}
I keep getting the following error in GCC when compiling...
error: no match for ‘operator=’ (operand types are ‘SBL’ and ‘long int’)
sbl = NULL;
^
This error basically is for the line sbl = NULL and it would be great if someone could explain to me exactly what that error actually means.
It can't find the operator= for SBL &SBL::operator=(const long int &rhs). There is a better practice. One option is to use a pointer and set it to NULL. NULL evaluates to 0. There is no operator which assigns an int intriniscally to your SBL struct object.
Or define a const static instance of the struct with the initial values and then simply assign this value to your variable whenever you want to reset it.
For example:
static const struct SBL EmptyStruct;
This uses static initialization to set the initial values.
Then, in init you can write:
sbl = EmptyStruct;
Note: Have to compile with -fpermissive in gcc or set EmptyStruct = { }. The reason why you have to set -fpermissive is listed here for GCC 4.6. GCC 4.4 needs EmptyStruct = { }.
Here is your program running. Initially it prints "initial" twice and on the third time, it prints empty string. Meaning, it was set to nothing by the assignment in the init function.
int main()
{
struct SBLnode initial;
initial.name = "initial";
struct Queue q;
q.first = &initial;
cout << q.first->name << endl;
struct SBL testInit;
testInit.q = q;
SBL_init(testInit);
cout << testInit.q.first->name << endl;
return 0;
}
http://ideone.com/Ecm6I9
void SBL_init (SBL& sbl) {
sbl = NULL;
}
Others have already pointed out why that line doesn't compile. Perhaps I can suggest an alternative solution. Instead of providing an init function, why not give all of your structures constructors like so? Is there some reason that you can't provide those? The operator= and copy constructor don't need to be defined if shallow copying of pointers is what you want. Since nodes typically need to be moved around I'm guessing that a shallow copy is fine. You can certainly use the nullptr if using c++ 11 rather than 0. I'm not a big fan of the NULL macro and opinions often vary with regards to NULL.
struct SBL {
SBL() : root(0) {}
Queue q;
BST root;
};
struct Queue {
Queue() : first(0), last(0) {}
SBLnode * first, * last;
};
NULL is a macro which expands to the integer literal 0. There is no intrinsic or user-defined operator which can assign an integer to an object of type SBL.
It looks like you are treating sbl as a pointer; but it is not a pointer, it is a reference.
You probably wanted to write this instead:
void SBL_init (SBL& sbl) {
sbl.root = NULL;
}
This initializes sbl by nulling out its member pointers.
As others have commented, nullptr is preferred in C++11:
void SBL_init (SBL& sbl) {
sbl.root = nullptr;
}
This error means that operator= , which is a function, is not defined in struct SBL. It is required when you write
sbl = NULL;
Solution:
provide SBL& operator=( const long int& i); in struct SBL.
In fact I think that you would like something alike SBL& operator=( BST b):
struct SBL {
Queue q;
BST root;
SBL& operator=( BST b) {
root = b;
return *this;
}
};
It is trying to find an assignment operator that has the form
SBL &SBL::operator=(const long int &rhs):#
and cannot find one.
I guess you were thinking about the pointers.

Linked-list in C++ using references instead of pointers

Suppose I want to create an unmodifiable linked-list (i.e. it can only be traversed, no nodes can be added or removed once it was initially created). This could be easily implemented by:
struct ListNode
{
int value;
ListNode* nextNode;
}
My question is .... Would it be possible to use references instead of pointers?
struct ListNodeWithRefs
{
int value;
ListNodeWithRefs &nextNode;
}
I am not sure it would provide any performance gain at all but ... this question popped up while coding and my answer so far is no but I could be missing something.
In principle, nothing prevents you from using references, and constructing list elments like this:
ListNodeWithRefs::ListNodeWithRefs(ListNodeWithRefs &next):
nextNode(next)
{}
But there is a chicken and egg problem because next also enforces its next element to exist at its creation and so on ...
Note: I think my question can also be applied to defining the list as:
struct ListNodeConst
{
int value;
const ListNode* nextNode;
}
This is typical of a cons-list in functional languages:
data List a = Empty | Node a (List a)
The trick is though, List a is a full type and can refer either to Empty OR another node (which is why it can terminate).
In order to achieve this in C++, you could take advantage of either a union (but it's not that well supported) or of polymorphism.
template <typename T>
struct ListBase {
enum class Kind { Empty, Node };
explicit ListBase(Kind k): _kind(k) {}
Kind _kind;
};
And then:
template <typename T>
struct EmptyList: ListBase<T> {
EmptyList(): ListBase<T>(Kind::Empty) {}
};
template <typename T>
struct ListNode: ListBase<T> {
ListNode(T const& t, ListBase<T>& next):
ListBase<T>(Kind::Node), _value(t), _next(next) {}
T _value;
ListBase<T>& _next;
};
And now, you don't have a chicken & egg problem any longer; just start from an instantiation of EmptyList<T>.
Note: the presence of _kind in the base class is not that OO, but it makes things closer to the functional example by tagging which alternative is used.
Take a look at this example by sbi, it seems to work: https://stackoverflow.com/a/3003607/1758762
// Beware, un-compiled code ahead!
template< typename T >
struct node;
template< typename T >
struct links {
node<T>& prev;
node<T>& next;
link(node<T>* prv, node<T>* nxt); // omitted
};
template< typename T >
struct node {
T data;
links<T> linked_nodes;
node(const T& d, node* prv, node* nxt); // omitted
};
// technically, this causes UB...
template< typename T >
void my_list<T>::link_nodes(node<T>* prev, node<T>* next)
{
node<T>* prev_prev = prev.linked_nodes.prev;
node<T>* next_next = next.linked_nodes.next;
prev.linked_nodes.~links<T>();
new (prev.linked_nodes) links<T>(prev_prev, next);
next.linked_nodes.~links<T>();
new (next.linked_nodes) links<T>(next, next_next);
}
template< typename T >
void my_list<T>::insert(node<T>* at, const T& data)
{
node<T>* prev = at;
node<T>* next = at.linked_nodes.next;
node<T>* new_node = new node<T>(data, prev, next);
link_nodes(prev, new_node);
link_nodes(new_node, next);
}
How does the list end?
You will need at least two types: the end and not. You also need lifetime management. And either runtime or static knowledge of which type.
A completely static implementation could be done, where each node is its own type that knows how far it is to the end.
Or you could just have an unintialized buffer, and create elements off it in reverse order.
A circle is also possible. Make the first reference refer to the last element you construct.
No. Reasons:
You cannot insert a node if nextNode is a reference.
What should nextNode refer to if this is list tail?
As #Vlad said, the problem with references is that you will need a final object.
The good news is that, in principle, you can still have a cyclic list, if you have a use for it.
This is a fundamental thing, if the "next" element is a non-nullable reference means that there is always a next element, that is, the list is either infinite or, more realistically, it closes on itself or into another list.
Taken the exercise further is quite interesting and strange.
Basically the only thing that seems to be possible is to defined the equivalent of the a node (which also represents the list).
template<class T>
struct node{
T value; // mutable?
node const& next;
struct circulator{
node const* impl_;
circulator& circulate(){impl_ = &(impl_->next); return *this;}
T const& operator*() const{return impl_->value;}
friend bool operator==(circulator const& c1, circulator const& c2){return c1.impl_ == c2.impl_;}
friend bool operator!=(circulator const& c1, circulator const& c2){return not(c1==c2);}
};
circulator some() const{return circulator{this};}
};
The elements have to live in the stack and the list is static (well, references are not rebindable anyway) and the links have to be const references!
Eventually the value can be made then mutable apparently (probably safe?).
(At this point one wonders how is this different from a stack array references by a modulo indices.)
There is only one way to construct the node/list object, that is to close it with itself (or with other preexising node). So the resulting list are either circular or "rho" shape.
node<int> n1{5, {6, {7, n1}}};
auto c = n1.some();
cout << "size " << sizeof(node<int>) << '\n';
do{
cout << *c << ", ";
c.circulate();
}while(c != n1.some()); //prints 5, 6, 7
I wasn't able to make a node that is not trivially constructible (aggregate?).
(Adding any sort of basic constructor produced segmentation faults for a reason I can't understand, both in gcc and clang).
I wasn't able to encapsulate the node in a "container" object for the same strange reason.
So making an object that could be constructed like this was impossible to me:
circular_list<int> l{1,2,3,4}; // couldn't do this for obscure reasons
Finally, since a proper container cannot be constructed it is not clear what is the semantics of this object, for example when two "lists" are equal? what doesn't mean to assign? or assign between list of different sizes?
It is a quite paradoxical object, with no general value or reference semantics apparently.
Any comments or improvements are welcomed!
I might be off the mark, but this works
struct Node;
struct Node {
using link = std::reference_wrapper<Node>;
Node( char data_ = 0)
: next({*this})
, data( data_ == 0 ? '?' : data_ )
{}
bool is_selfref() const noexcept {
return (this == & next.get());
}
char data;
link next;
};
The usual tests
Node A('A');
Node B('B');
Node C('C');
assert( A.is_selfref() == B.is_selfref() == C.is_selfref());
A.next = B; B.next = C;
assert(! A.is_selfref() && ! B.is_selfref() );
assert( C.is_selfref() );
assert( 'A' == A.data );
assert( 'B' == A.next.get().data );
assert( 'C' == A.next.get().next.get().data );
// C.next == C
// for those who feel safe seeing the END
Node END(127);
C.next = END;
Of course, as long as all Node's stay in the scope we are all ok here. Otherwise not. Strange and wonderful. Very limited utility?
That was quite tricky but this worked :
#include <iostream>
#include <typeinfo>
class Last {
public:
int x;
int last;
Last(int i) {
std::cout << "parent constructor(" << i << ")\n";
x = i;
last = 1;
}
};
struct fourptr {
int v1, v2;
void *p1, *p2;
};
class chain : public Last {
public:
chain(int i) : Last(i) {
std::cout << "child constructor(" << i << ")\n";
last = 0;
}
void viewandnext() {
struct fourptr *fp = (struct fourptr *) this;
std::cout << x << ", this = " << this
<< ", sizeof *this = "<< sizeof * this
<< ", * this = {" << fp->v1 << ", " << fp->v2 << ", "
<< fp->p1 << ", " << fp->p2 << "}"
<< "\n";
if (last == 0) ((chain &)next).viewandnext();
}
Last & fn(int x) {
Last * e = (x>0) ? new chain(x-1) : new Last(x-1);
return *e;
}
Last & next = fn(x); // This is not a pointer but a reference
};
int main(void) {
chain &l = *(new chain(8));
std::cout << "sizeof l = "<< sizeof l << "\n";
l.viewandnext();
}
A simple way to avoid a chicken-egg problem for a list with references is to remember that firstly your object memory is allocated, then your constructor is called. Moreover, access to this pointer is guaranteed inside of a constructor by C++ standard.
Neat way to resolve this:
struct node {
int data;
node& next;
node(node& n, int d): next(n), data(d) {}
};
node tl(tl, 69); // tl is already in the scope!