Return a node class - c++

My professor has asks us to reimplement all of the LinkedList functions from scratch. However, since this is a beginner class, he has put a few stipulations on it. Below is the full assignment:
"For list, you must implement everything but get_allocator. For all functions that take an "iterator" as an argument, instead accept a node class. For all functions that return an iterator, return a node instead."
Since LinkedList use pointers, I am not sure how to do return a node without just returning a pointer. What would be the syntax for returning a node pointed to by a pointer called *current?
I am also unsure how to format the functions. For example, what would be the syntax for changing the following function to accept a node class and then return a node(i don't need the code for the function, just how to accept a node and return a node class):
iterator insert (iterator position, const int&x)

"For list, you must implement everything but get_allocator. For all
functions that take an "iterator" as an argument, instead accept a
node class. For all functions that return an iterator, return a node
instead."
Since LinkedList use pointers, I am not sure how to do return a node
without just returning a pointer. What would be the syntax for
returning a node pointed to by a pointer called *current?
I think your professor is talking about accepting and returning pointers (or references) to nodes, not node values (copying nodes). I can say that with some degree of confidence because that's the only way to preserve the underlying semantics of std::list with a one-to-one translation of iterators to nodes (node pointers).
However, if your nodes are just mere aggregates storing pointers themselves and don't try to do any memory management, then you can get away with copying them around, but I'd go with pointers if in doubt.
So, something like this:
iterator insert(iterator position, const T& val)
{
...
}
Would look like this for your practice homework:
LinkedListNode* insert(LinkedListNode* position, const T& val)
{
...
}
If you aren't using templates and can just make it a list of integers or whatever:
LinkedListNode* insert(LinkedListNode* position, int val)
{
...
}
Hope later your professor will make you appreciate the power of the iterator-based versions as those allow you to write function templates that work not only on linked lists but any kind of sequence, for example.

I think you shouldn`t use pointers. Try to use reference or iterators?

To dereference a pointer, use the * operator. For example, if you have a valid pointer-to-int, and you want access to use the int that it points to:
*pointer_to_int = 5;
j = *pointer_to_int / 3;
and so forth. Similarly, if you want to pass the value of the pointed-to-int to a function,
k = SomeFunction(*pointer_to_int, 12, foo);
or return it from a function:
int Function() {
return *pointer_to_int;
}
You can use the syntax *pointer anywhere you might otherwise say, variable.
The syntax for declaring functions that return a type doesn't change based on the type. Suppose you have some function that returns an int:
int MyFunction() { return my_int; }
Or, if it returned an iterator:
iterator MyFunction() { return my_iterator; }
Or, if it returned an Apple:
Apple MyFunction() { return my_apple; }
You see, you just need to replace the name of the return type with whatever type you are returning.
Hopefully, you can see now how to declare a function that returns a node object, and how to return a node object, given that you only have a pointer_to_node.

Related

Qt C++11 Handing out raw pointer from QList

I am working on a problem where I have some sort of custom made "container" DTO which contains a series of items. The user of the class should be able to retrieve an item at a position from the container. I wanted the container to not keep a refrence of raw pointers to the items it contains, but really own them so no custom destructor is necessary. This is what I came up with:
#include <QList>
class MyItem {
public:
MyItem(int n) : number(n){}
private:
int number;
};
class MyContainer {
public:
void addItem(MyItem item){
m_items.append(item);
}
MyItem* getItemAt(int pos){
if(pos < m_items.size() && pos >= 0){
return &(m_items.at(pos));
}
return nullptr;
}
private:
QList<MyItem> m_items;
};
int main(){
MyContainer container;
MyItem item1(4);
container.addItem(item1);
MyItem* item_ptr = container.getItemAt(0);
return 0;
}
And in the return of the getItemAt function I am getting this error:
main.cpp:21:24: error: cannot initialize return object of type 'MyItem *' with an rvalue of type 'const MyItem *'
My function needs to return a non const value, because the caller needs to modify the retrieved object. Is there a way to fix this? Is this the best solution for avoiding the destructor and indicating to the caller that the return value is empty.
I know there are several ways to do this:
return an optional: unfortunately I am bound to C++11 so not an option
throw an exception: I really dislike this option since the codebase has 0 exceptions atm, and I rather not introduce them here.
Returning a pointer to a memory address inside the QList storage is ill-advised. From the QList documentation "be aware that any non-const function call performed on the QList will render all existing iterators undefined". If the inner container stored actual pointers then that would not be a problem. These could even be smart pointers that eliminate the need of writing a destructor.
However I also see that you are passing by value to add an item. If passing by value is acceptable there then why not for the return? This is an inconsistent interface.
It sounds like you want to really want to pass and return by reference, e.g. add(const MyItem&) and MyItem& get(int).
As noted by rafix, QList's operator[](idx) returns a non const reference, so you can simply return that.
Then how will you do bounds checking? There are multiple ways but the easiest is to just add a size() method.

How do I access pointer to Structure instead of its elements from iterator in STL list

I have a structure of the following form
class THistory
{
/* */
public:
UInt32 userId;
UInt32 trip;
};
List looks like follows
THistory hist2;
std::list<THistory> temp;
std::list<THistory>::iterator it = temp.begin();
hist2.userId=userId;//passed by some function storing in tempory structure
hist2.trip=trip;//passed by some function storing in tempory structure
temp.push_back(hist2);//Pusing into list
My problem is I can access
it->userId and
it->trip
but HOW do I access entire structure. I need to pass entire structure pointer to some other function rather than individual elements. Also, is the above approach correct of using temporary sturcture to populate the elements of structure before pushing into list.
UPDATING based on answers:
I pass the iterator as follows
getLocations(&*it);
definition:
getLocations( THistory *hist){
////
}
My code builds but, it crashes at runtime
"Error: Iterator is deferencable" I steped inside the function, it hits list function call internal to library and crashes here
reference operator*() const
{ // return designated value
return ((reference)**(_Mybase *)this);
}
I am getting confused. Hope it is not silly error
To get the structure, you use the dereference operator * on the iterator. And to get a pointer to the structure you use the address-of operator &.
So e.g. &*it
But (and this is very important) you should first check if the iterator is actually referencing a valid element in the list. The way you show the code in your example, the list is empty and temp.begin() will return the temp.end() iterator, which shouldn't be dereferenced.
However I fail to see why you need a pointer, unless the function you need to call was written by someone else. If you have written, or can rewrite the function, then change it to use a reference (or a reference to a constant) to the structure, and you don't need to use pointers. You really should avoid pointers as much as you can in C++.
As for adding elements to the list, then what you show should work just fine. But if you add a constructor taking the required arguments then you don't need a temporary variable, and could to e.g.
temp.push_back(THistory(userId, trip));

Can't get my constness right

I have a Node class defined like this (this is a minimal version):
class Node {
private:
std::vector <const Node*> leaves;
public:
Node* getLeaf(int i);
}
In other words, I want getLeaf to return a pointer to an element of the vector "leaves"
I tried defining getLeaf like so
Node* Node::getLeaf(int i){
return leaves[i];
}
Ok, so I know I'm screwing the constness up. I've tried variations of const modifiers in my function declarations / definitions to no luck. Someone please help :)
const is a promise to not change.
You declare a vector of pointers to const nodes. That's a promise to not change any Node via these pointers.
The getLeaf function can't very well then return a pointer to non-const node, because then the caller can do anything with the node.
So you have to make either the same promise both places, or don't make any such promise.
Another matter is whether getLeaf itself should be const (it probably should, it makes sense to let it promise not to change the object), and a second other matter is whether get makes sense as a prefix in C++ (usually not, it's just needless verbosity, while in Java there are tools that can make good use of such of prefix), I'd just call it node.

Passing the pointer to the first element of a vector if any

I have a function taking double*
void funct(double*);
and I have a vector:
std::vector<double> myVec;
how should I correctly and safely call funct(myVec)?
not safe:
funct(&myVec[0]);
funct(&*myVec.begin());
not nice to be read:
funct( myVec.empty()? NULL : &myVec[0]);
funct( myVec.empty()? NULL : &*myVec.begin());
any suggestion?
What's the standard approach?
Well, the standard class type std::vector has a member function called data, that is supposed to return the pointer to the underlying storage. Apparently data() is nothing more than &front() with the guaranteed that:
The pointer is such that range [data(); data() + size()) is always a valid range, even if the container is empty.
Therefore I'd say that both:
funct(vector.data());
funct(&vector.front());
can be safely used.
But the real question is: what are you trying to do inside the function?
I can see 3 obvious answers to this, and I'm going to propose alternatives for all:
I only want one element of the array
I want an optional argument
I want to pass a container
Let's start with the first, shall we? If you only want an element of the array, why bother with pointers and array in general? You can just use:
void funct(double);
and be done with it. And if you want to modify that double, why not pass it by reference?
void funct(double&);
and call the function as:
funct(vector[0]);
The number two has two very possible answers. One is to use function overloading like this:
void funct();
void funct(double);
And basically consider the function with no argument and an argument. The simplest solution is probably the right one, correct?
Otherwise, if you are really feeling fancy and you can't be bothered to write funct two times, you can even use boost::optional or std::optional (C++14), which clearly express the intent of the argument:
void funct(std::optional<double> optional) {
if (optional) {
// we have a double
} else {
// we don't have a double
}
}
And finally, the third one has three possible answers (can you see the pattern?).
If you only want a specific kind of container (why would you want that, only God knows) you can simply do:
void funct(const std::vector<double>&);
Otherwise you can either use templates like Bartek explained below or use my favorite solution: iterators (which is the choice of standard algorithms as well, just to make it less official).
And guess what? It works also with C-style arrays (which you shouldn't be using by the way). Here's the solution:
template<class Iterator>
void funct(Iterator begin, Iterator end) {
for (auto it = begin; it != end; ++it) {
// do something to element (*it)
}
}
And BOOM. You can use it like this:
double x[100];
funct(std::begin(x), std::end(x));
or:
std::vector<double> x(100);
funct(x.begin(), x.end());
Happy coding.
std::vector has member function data. So you can use it like this:
func(nyVec.data());
I did not find in the Standard that if a vector is empty then data has to return 0. Maybe it is a Standard defect. Though an empty vector can has non-zero capacity.
If you need to check whether a vector is empty then you can write:
func(myVec.empty() ? NULL : nyVec.data());
Usually if you pass an array by value you should specify a second parameter that will contain the size of the array. So maybe it would be better if func was declared as:
func(double *, std::vector<double>::size_type);
In this case you could call the function as:
func(myVec.data(), myVec.size());
If you need to process only one element then the standard approach is the following:
if (!myVec.empty()) func(&myVec.front());
Try
funct(&myVec.at(0));
This performs bounds checking and will throw std::out_of_range if element is not within the range of the container.
Create a utility function. This will both hide the not-niceness and prevent code duplication.
template <class T>
typename T::value_type* first_ptr(T &&container)
{
return container.empty() ? nullptr : &container.front();
}
int main()
{
funct(first_ptr(myVec));
}
I would wrap or change the function into more idiomatic optional primitive:
void funct(optional<double&> f);
Let's think about the passing then. The function should, if the vector is not empty, pass the first element, and nothing otherwise.
Directly transcribes to
if (!v.empty()) {
funct(v.front());
} else {
funct(none);
}
I would probably change it to regular value semantics, though; referencing elements from collections directly is rather dangerous.
Of course you can pack it into a reusable function:
template<class Container>
optional<typename Container::value_type&> myFront(Container& cont) {
if (!cont.empty())
return cont.front();
else
return none;
}
funct(myFront(v));
Now you only need lift :).
std::vector data() member function returns a pointer to its internal data (array), so we can use it this way:
if ( !(myVec.size() == 0)) func( myVec.data());
or:
if ( !myVec.empty()) func( myVec.data());
The choose of size() or empty() is dependent on implementation of these functions that you are using. C++ standard guarantees that empty() is constant time for all standard containers.
Not really an answer but anyway: this seems like an XY problem.
I would say none of the solutions proposed in the OP are good fits based on the following: it makes little sense to be calling a function with a null pointer argument so I would say this should be handled at the call site. Something like:
if(!myVec.empty()) funct(&myVec[0]);
else ...

Erasing from std::list<Value> using a raw pointer to Value?

I have an std::list<Value> that belongs to a managing construct, handing out Value * pointers whenever a factory method is called. These pointers are passed back to the manager when the Value needs to be destroyed. However, I'm unsure how best to use these pointers to find and erase/remove the element.
class ValueManager{
public:
Value * createValue(ValueDef & def) {
m_valueList.push_back( Value( def ) );
return &m_valueList.back();
}
void destroyValue(Value * target) {
// Mystery!
// How does one remove/erase a list element
// with only a pointer to it's value?
}
private:
std::list<Value> m_valueList;
};
Both ::erase and ::remove seem ill fit to the task, one takes an iterator instead of a pointer, and the latter takes an entire value, which can't be done because, in this case, there is no acceptable == comparison method between Values, only the pointer can reliably be used to find the target.
My question, is what is the most efficient implementation destroyValue() could take on?
Simple: stop returning raw pointers, and start returning iterators. Then the user who wants to destroy one will pass in the value received when it was created, just like now. And dereferencing will still work as it does with a raw pointer. But erase will also work, and be efficient.