So I have two classes inside the same file; ArrayLinkedList and ArrayLinkedListRow
Inside the first mentioned one I have a method
template<class T> friend ostream& operator <<(ostream& s, ArrayLinkedList<T>& ll){
//Extra code for giving s content
return s;
}
as well as having
template<class T> friend ostream& operator <<(ostream& s, ArrayLinkedListRow<T>& ll){
//Extra code for giving s content
return s;
}
inside of ArrayLinkedListRow.
I get the following error
Error 1 error C2995: 'std::ostream &operator <<(std::ostream
&,ArrayLinkedList &)' : function template has already been
defined
and it's driving me nuts not knowing how to fix it. I have done my research, but still I cannot figure out what to do. I strongly believe that the two classes might be related in the problem, despite of the error just pointing out to one line.
Extra Info:
This is the class ArrayLinkedList header for those who feel confused with my short explanation.
template<class DT>
class ArrayLinkedList {
private:
DT* _info[MAX_SIZE]; // store data
int _next[MAX_SIZE]; // next node
int _nextEmpty[MAX_SIZE]; //next empty slot
ArrayClass< ArrayLinkedListRow<DT> >* _rows;
int _head; // head of the list
int _firstEmpty; // first empty slot
int _size;
void copy(const ArrayLinkedList<DT>& ll);//copy from another list
// add a new node with next as it's next node and returns the index of new node
int newNode( DT& newObject, int next);
public:
ArrayLinkedList(); // empty and copy constructors
ArrayLinkedList(const ArrayLinkedList<DT>& ll);
//copy constructors linked list object to an existing object. This is a deep copy.
~ArrayLinkedList(); // destructor
ArrayLinkedList(DT& newObject); // Constructor that create a list with newObject as the head
ArrayLinkedList(int capacity); // Constructor with a give capacity
ArrayLinkedList(DT& newObject,int capacity);// Constructor with newObject as the head and capacity
bool isEmpty(); // is the list empty?
int size(); // return the number of nodes stored
void add(DT& newObject); // add an object to the tail
void insertAt(DT& newObject, int position); // insert an object at the position specified
DT remove(); // remove the head
DT removeAt(int position); // remove an object at the position specified
int find(DT key); // find the object that matches key, index of the object
void operator=(const ArrayLinkedList<DT>& ll); // = operator
// overloading [] operator, return a reference to object at the
// Add a new data element to the start of a linked list.
DT& operator[] (const int position); // position in the linked list
// ostream operator
template<class T> friend ostream& operator <<(ostream& s, ArrayLinkedList<T>& ll){
return s;
}
void displayRaw(); // display raw data of the data members
};
Try to remove the template<class T> part:
friend ostream& operator <<(ostream& s, ArrayLinkedList& ll){
//Extra code for giving s content
return s;
}
// and analogically with ArrayLinkedListRow
The reason why this works is stated here:
If you declare a variable ArrayLinkedList<int>, then and only then the operator << is created with the template-parameter T and DT (which is unused). If you compile this, everything works fine.
If you add a variable of type ArrayLinkedList<float>, then the operator gets defined a second time and this creates the error.
Working only with DT makes it work as expected.
Related
I am new to the topic of overloading copy constructors and I just wanted someone to look at my code for my class and see if I am overloading my copy constructor correctly. It is only using a single string as user input. Also, do I need the '&' or not?
class TODO {
private:
string entry;
public:
List* listArray = nullptr;
int itemCount = 0, currInvItem = 0;
int maxLength = 22;
TODO() { entry = ""; };
TODO(const string& ent) { setEntry(ent); }; // Is this correct?
void setEntry(string ent) { entry = ent; };
string getEntry() const { return entry; };
void greeting();
void programMenu();
void newArray();
void getList();
void incList();
void delTask();
string timeID();
string SystemDate();
friend istream& operator >>(istream& in, TODO& inv);
friend ostream& operator <<(ostream& out, TODO& inv);
void componentTest();
void setTask(string a);
string getTask();
bool validTask(string a);
bool notEmpty(string e);
};
That's correct, but it's just a constructor of TODO taking a const reference to a string. You can test it here.
Passing const string& ent (by const reference) is not a bad idea. Another option would be to pass string ent (by value), and move that string when initializing entry, i.e. : entry{ std::move(ent) }. As here.
The class TODO has a default copy constructor. Check the line at the Insight window here (you'll have to click Play first).:
// inline TODO(const TODO &) noexcept(false) = default;
The default copy constructor would just copy the members, including the List pointer, but not the List elements (shallow copy). Notice both instances of TODO would be pointing to the same List elements, and any operation on them would affect both instances.
Should you want to implement a custom copy constructor, the syntax would be (see here):
TODO(const TODO& other) {
std::cout << "custom copy_ctor\n";
*this = other;
// Copy listArray elements
...
}
While trying to create a Binary Search Tree (BST) using C++11 I hit a snag.
I can't extract a properly created BST out of the function where it is created.
The function reads data from a file (in this case just a number on each line) and builds a BST from those. The building part in the loop works correctly.
The problem is I can't get the temporary object moved where I want it to be.
Zooming in on the problem I think, see edit 3.
More context:
BST<T> is a class that derives publicly from std::unique_ptr<BSTknoop<T>>
BST<T> also inherits the constructors of unique_ptr<BSTknoop<T>> with
template<class T>
using BSTknoopptr=std::unique_ptr<BSTknoop<T>>; // alias template
and
using BSTknoopptr<T>::BSTknoopptr; // in the body of the BST<T> class declaration`
A BSTknoop<T> is a data structure with 3 fields
one T object to hold the node data
two BST<T> objects left and right (each child is a tree in its own right)
the goal is to move my newly created BST into the calling object. The idea is that in main you can call BST<int> tree; tree.lees(ifs); (with ifs an open input filestream) and tree holds the properly filled BST afterwards.
The function:
template<class T>
istream& BST<T>::lees(istream& is){
string lijn;
T knoopwaarde;
getline(is,lijn);
knoopwaarde = stoi(lijn);
BST<T> temptree(new BSTknoop<T>());
temptree->sl = knoopwaarde;
for(int i=1; i<DATA_SET_LENGTH ; i++){
getline(is,lijn);
knoopwaarde=stoi(lijn);
temptree.add(knoopwaarde);
cout<<temptree;
}
this->swap(temptree); /* This does not work */
/* *this = move(temptree); this does not work either*/
return is;
}
I have also tried to return a BST<T> from the function and moving that result in the main. That didn't work either.
The program crashes at runtime with an unknown signal.
Side note: I'm unsure as to why BST<T> temptree(new BSTknoop<T>()); works in regard to the templating. The construction works because BST<T> inherits the constructors for unique_ptr<BSTknoop<T>>
edit 1: the declaration of the BST<T> class:
template <class T>
class BST:public BSTknoopptr<T>{
using BSTknoopptr<T>::BSTknoopptr;
public:
friend istream& operator>>(istream& is, BST<T>& bb){
return bb.lees(is);
}
friend ostream& operator<<(ostream& os, const BST<T>& bb){
//return bb.schrijflevelorder(os);
return bb.schrijfKnoop(os);
}
void add(const T&);
ostream& schrijf(ostream&);
ostream& schrijfKnoop(ostream&) const;
int aantalSleutels() const;
istream& lees(istream&);
ostream& schrijflevelorder(ostream& os) const;
private:
};
the declaration of theBSTknoop<T> class:
template <class T>
class BSTknoop{
friend class BST<T>;
public:
BSTknoop() {}
explicit BSTknoop(T _sl) : sl(_sl) {}
private:
T sl;
BST<T> links,rechts;
};
edit 2: I've written a move constructor and move assignment operator. I've made sure to retain the default constructor as well using BST<T>()=default; I'm confused though: the BST class doesn't have any members for which I would have to implement my own move constr / operator.
However, BST has inherited from unique_ptr<BSTknoop<T>>so implicitly, it must hold a member of that type. Suppose I want to keep the inheritance, is there any neat way to make this work?
Is is also true that I can't (or perhaps shouldn't) implement a copy constr / operator as those are deleted for unique_ptr?
template<class T>
BST<T>::BST(BST<T>&& other){
*this = move(other);
}
template<class T>
BST<T>& BST<T>::operator=(BST<T>&& other){
cout<<"called move operator BST"<<endl;
(*this).BSTknoopptr<T>::operator=(move(other));
return *this;
}
edit 3: with my own move constr / operator, the temptree no longer gets filled properly. Below is my code for add which is used to build the tree. If I omit my own move constr / operator, then this works. What I need is an operation that works like this->get()->links = move(tmp).
types this->get()->links => BST<T>
tmp => BST<T>
How come this works? It does the operation I need, why can't I use something similar to do *this = move(temptree) by writing the operation myself.
template<class T>
void BST<T>::add(const T& value){
if(value <= this->get()->sl){
if(this->get()->links != nullptr){
this->get()->links.add(value);
}
else {
BST<T> tmp(new BSTknoop<T>(value));
this->get()->links = move(tmp);
}
}
else{
if(this->get()->rechts != nullptr){
this->get()->rechts.add(value);
}
else{
BST<T> tmp(new BSTknoop<T>(value));
this->get()->rechts = move(tmp);
}
}
}
Okay, I made the stupidest mistake. There is nothing wrong with the inheritance and accompanying move semantics. I used the DATA_SET_LENGTH preprocessor directive inside my istream& BST<T>::lees(istream& is) function. While my final dataset will hold a million items. My dataset for testing purposes only holds 12. I forgot to change the value of DATA_SET_LENGTH so stoi(lijn) crashed.
For anyone interested in the solution:
notes
You don't need to write much code to make this work.
It is possible to write BST<T>& operator=(BSTknoopptr<T>&&); yourself and it works. However even without explicitly writing your own it also works.
The BST class has no fields of pointer type so we don't get into trouble with unique_ptr not having a virtual destructor
Final question (perhaps someone can comment):
The inherited operator operator=(BSTknoopptr<T>&&), what does its signature look like in BST<T>? Mostly in regards to return type (if it's now a member of BST<T> what type does it return?).
** TLDR: why can I rely on the inherited move operator / move constructors of unique_ptr<BSTknoop<T>>? **
bst.h
#define DATA_SET_LENGTH 12
using namespace std;
template <class T>
class BST;
template <class T>
class BSTknoop;
template<class T>
using BSTknoopptr=std::unique_ptr<BSTknoop<T>>;
template <class T>
class BST:public BSTknoopptr<T>{
using BSTknoopptr<T>::BSTknoopptr;
public:
BST<T>& operator=(BST<T>&&) = default;
BST<T>(BST<T>&&) = default;
BST<T>()=default;
//BST<T>& operator=(BSTknoopptr<T>&&);
friend istream& operator>>(istream& is, BST<T>& bb){
return bb.lees(is);
}
friend ostream& operator<<(ostream& os, const BST<T>& bb){
//return bb.schrijflevelorder(os);
return bb.schrijfKnoop(os);
}
void add(const T&);
//schrijf schrijft uit in een vorm die min of meer menselijk leesbaar is
ostream& schrijf(ostream&);
ostream& schrijfKnoop(ostream&) const;
int aantalSleutels() const;
istream& lees(istream&);
//schrijflevelorder schrijft uit in een vorm die door lees(...) kan gelezen worden.
ostream& schrijflevelorder(ostream& os) const;
private:
};
template <class T>
class BSTknoop{
friend class BST<T>;
public:
BSTknoop() {}
explicit BSTknoop(T _sl) : sl(_sl) {}
private:
T sl;
BST<T> links,rechts;
};
//template<class T>
//BST<T>& BST<T>::operator=(BSTknoopptr<T>&& other){
// cout<<"called BST<T> move with BSTknoopptr r-value ref argument"<<endl;
// (*this).BSTknoopptr<T>::operator=(move(other));
// return *this;
//}
template<class T>
void BST<T>::add(const T& value){
if(value <= this->get()->sl){
if(this->get()->links != nullptr){
this->get()->links.add(value);
}
else {
//BSTknoopptr<T> tmp(new BSTknoop<T>(value)); if used with my own BST<T>& BST<T>::operator=(BSTknoopptr<T>&& other)
BST<T> tmp(new BSTknoop<T>(value));
this->get()->links = move(tmp);
}
}
else{
if(this->get()->rechts != nullptr){
this->get()->rechts.add(value);
}
else{
//BSTknoopptr<T> tmp(new BSTknoop<T>(value)); if used with my own BST<T>& BST<T>::operator=(BSTknoopptr<T>&& other)
BST<T> tmp(new BSTknoop<T>(value));
this->get()->rechts = move(tmp);
}
}
}
template<class T>
istream& BST<T>::lees(istream& is){
string lijn;
T knoopwaarde;
getline(is,lijn);
knoopwaarde = stoi(lijn);
BST<T> temptree(new BSTknoop<T>());
temptree->sl = knoopwaarde;
for(int i=1; i<DATA_SET_LENGTH ; i++){
getline(is,lijn);
knoopwaarde=stoi(lijn);
temptree.add(knoopwaarde);
cout<<temptree;
}
*this = move(temptree);
return is;
}
main.cpp
int main(){
ifstream ifs;
ifs.open("c.dat");
if(ifs.is_open()){
BST<int> tree;
tree.lees(ifs);
tree.schrijfKnoop(cout);
}
else {
cerr<<"failed to open file"<<endl;
return -1;
}
}
I am writing program which has a multitude of Directed Graph helper functions in order to gain a deeper understanding of C++. One of the central objects is called a Node which has member functions to help with calculating travel distance between nodes. I am trying to gain a better understanding of using C++ templates in OOP design.
Here is a quick snapshot of the Node class
class Node {
friend void swap(Node & first, Node & second) {
using std::swap;
swap(first.name, second.name);
}
public:
Node(std::string val);
Node(const Node & copy);
Node & operator = (Node copy) {
swap(*this, copy);
return *this;
}
bool operator < (Node & rhs) const {
return (size < rhs.size);
}
bool operator > (Node & rhs) const {
return (size > rhs.size);
}
bool insertEdge(Node * dest, int distToNode);
// I'd like for this return type to not be tied to an int
// Especially if weights were represented as floats or doubles
int findTravelDistance(Node * const & toNode) const;
int findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
// Mutators
void setNodeName(const std::string nameToSet);
std::string getNodeName() const;
void setNodeSize(const int size);
int getNodeSize() const;
// Misc
void toString() const;
// Constants
static const bool ALLOW_CIRCULAR;
~Node();
protected:
private:
int size;
std::string name;
// Here int represents the weight of the edge. I would like it to be able to be
// declared as an int, float, long, or double etc...
std::map<Node *, int> * travelEdges;
}; // end class
} // end namespace
As I build this class to include more functionality, I find myself struggling with how to make my functions more adaptable. For instance, look at the findTravelDistance functions.
What I would like to do is have the return type representing weight be type agnostic and the ordered map data structure's value to be type agnostic. As it is currently implemented, a user can only declare a type int for the weight. I realize I could embark upon function overloading. But, I feel this would be too redundant and an obvious violation of the DRY principle. If I were to have to change how this function works, I would have to change it for every overload. So my gut instinct tells me I should use C++ templates. Since I am new to templates, I am struggling with where to declare it. If I make my find functions template functions and just return the generic type..
template<class T>
T findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
That will solve my problem there. But, it doesn't fix the issue where the underlying map data structure representing edges can only hold ints. My next thought was to declared a class template..
template<class T>
class Node { ... }
But this also seemed odd to me. This would mean declaration and initialization would look something like
Node<float> * n = new Node<float>("N");
If I were a user of my program, I would not immediately associate Node with the float type representing edge weights.
So what is the best or appropriate usage of a template in this case? Or is using a template even the correct path here? It is possible my class design is flawed to begin with and not very C++'esk. Any feedback here is much appreciated.
This is very clean code :). Welcome to C++!
I believe what you want to do is use a template variable to hold your edge weights. How about something like the following:
using std::swap;
template<class Distance>
class Node {
friend void swap(Node & first, Node & second) {
swap(first.name, second.name);
}
public:
Node(std::string val);
Node(const Node & copy);
Node & operator = (Node copy) {
swap(*this, copy);
return *this;
}
bool operator < (Node & rhs) const {
return (size < rhs.size);
}
bool operator > (Node & rhs) const {
return (size > rhs.size);
}
bool insertEdge(Node * dest, Distance distToNode);
// I'd like for this return type to not be tied to an int
// Especially if weights were represented as floats or doubles
Distance findTravelDistance(Node * const & toNode) const;
Distance findTravelDistance(std::queue<Node *> * const & nodeRoute) const;
// Mutators
void setNodeName(const std::string nameToSet);
std::string getNodeName() const;
void setNodeSize(const Distance size);
int getNodeSize() const;
// Misc
void toString() const;
// Constants
static const bool ALLOW_CIRCULAR;
~Node();
private:
int size;
std::string name;
std::map<Node *, Distance> * travelEdges;
}; // end class
As a bonus, I've moved your using declarations to the top of the class. Generally these go at the top of the file. You also might benefit from taking a look at the holy scripture that is the Parashift C++ FAQ, particularly the section on const correctness. Your comparator methods, for example, should have const Node& parameters.
This prints an error message about qualifiers but don't really understand what that means and how to adjust the code for it to work? Anyways, thanks a lot for looking at the code.
Note: The ostream operator is friended in the Node class.
using namespace std;
ostream& operator(ostream& output, const Node* currentNode)
{
return output;
}
void Node::nodeFunction()
{
//This node has items attached to the 'this' statement. After
//the necessary functions, this is called to output the items.
cout << this;
}
Your overloaded stream operator declaration should be like this:
std::ostream& operator<<(std::ostream& os, const T& obj);
^^^^^^^^^^^^^
You should be returning a reference to object of std::ostream, the & is wrongly placed in your overloaded function prototype.
Have a look at the working sample here.
Adding the source code here, for completeness.
Note: I have taken class Node members as public for ease of demonstration.
#include<iostream>
using namespace std;
class Node
{
public:
int i;
int j;
void nodeFunction();
friend ostream& operator <<(ostream& output, const Node* currentNode);
};
ostream& operator<<(ostream& output, const Node* currentNode)
{
output<< currentNode->i;
output<< currentNode->j;
return output;
}
void Node::nodeFunction()
{
//This node has items attached to the 'this' statement. After
//the necessary functions, this is called to output the items.
cout << this;
}
int main()
{
Node obj;
obj.i = 10;
obj.j = 20;
obj.nodeFunction();
return 0;
}
The & on the return value of the operator is in the wrong place, and it's generally better to use references rather than pointers for ostream operators:
ostream& operator<<(ostream &output, const Node ¤tNode)
{
// Output values here.
return output;
}
void Node::nodeFunction()
{
cout << *this;
}
I'm getting a mysterious error in my project that says:
expected constructor, destructor, or type conversion
It's not allowing me to use my overloaded operator<<. This previously worked before I made my class (myVector) into a template
//MyVector class
//An implementation of a vector of integers.
template <class T>
class MyVector{
public:
//Purpose: Initialize an object of type MyVector
//Parameters: none.
//Returns: nothing.
MyVector();
//------------------------------------------------
//Purpose: Initialize an object of type MyVector
//Parameters: an integer.
//Returns: nothing.
//------------------------------------------------
MyVector(int);
//Purpose: Destroys objects of type MyVector
//Parameters: none.
//Returns: nothing
//------------------------------------------------
~MyVector();
//Purpose: Returns the current size of the MyVector.
//Parameters: none.
//Returns: the size.
int size() const;
//------------------------------------------------
//Purpose: Returns the capacity of the MyVector.
//Parameters: none.
//Returns: int.
int capacity() const;
//------------------------------------------------
//Purpose: Removes the entries of MyVector.
//Parameters: none.
//Returns: nothing.
void clear();
//------------------------------------------------
//Purpose: Appends a given integer to the vector.
//Parameters: an integer.
//Returns: nothing.
void push_back(T);
//------------------------------------------------
//Purpose: Shows what's at a given position.
//Parameters: an integer index.
//Returns: an integer.
T at(int) const;
MyVector(const MyVector& b);
const MyVector& operator=(const MyVector&);
//------------------------------------------------
private:
int _size;
int _capacity;
int* head;
//Purpose: Increases the capacity of a MyVector when it's
// capacity is equal to it's size. Called by push_back(int)
//Parameters/Returns: nothing.
void increase();
//Purpose: Copies the given vector reference.
//Param: MyVector reference.
//Returns: nothing.
void copy(const MyVector&);
//Purpose: Frees MyVector up for an assignment.
void free();
};
template <class T>
ostream& operator<<(ostream&, const MyVector<T>);
//This line is giving me the error.
#endif
I have the code for the operator in a seperate file:
template <class T>
ostream& operator<<(ostream& os, const MyVector<T> V){
int N = V.size();
os << endl;
for(int i = 0; i<N; i++){
os << V.at(i)<<endl;
}
return os;
}
I've looked at other questions, but none seem to match mine. Help would be greatly appreciated. Thanks!
You probably need to qualify ostream with std as:
std::ostream& operator<<(std::ostream&, const MyVector<T>);
And you should almost certainly be passing your vector by const reference, rather than const value.
You can't declare a template in a file and then define it into another file. You can only define it.
Hope it helped you.
You should make the operator<< function accept a constant reference to the MyVector rather than just a constant, since what you are doing is to create a copy of the vector to pass into the function.
template <class T> std::ostream& operator<<(ostream& o, const MyVector<T>& V)
Expected constructor, destructor, or type conversion suggests that it does not recognize ostream as a type (ie, it has not been declared in this scope). Prefixing with std:: is not alone sufficient to resolve the issue; you must also include the dependent file.
#include <ostream>
No need to Declare this:
template <class T>
ostream& operator<<(ostream&, const MyVector<T>);
You can follow this
#include <iostream>
using namespace std;
template <class T>
class A
{
public:
A();
int _size;
};
template <class T>
ostream& operator<<(ostream&, const A<T> p)
{
cout<<"in ostream"<<endl;
}
template <class T>
A<T>::A()
{
_size = 90;
cout<<_size<<endl;
}
int main()
{
A<int> ob;
cout<<ob;
return 0;
}