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.
Related
I am starting using c++11 features and I like to use smart pointers only to own the objects. Here is my class:
class MyClass {
public:
vector<MyObject*> get_objs() const;
private:
vector<unique_ptr<MyObject>> m_objs;
};
The semantics is that MyClass owns a serial of MyObject which are created through make_unique(). get_objs() returns a vector of raw pointers in order for various callers to update the objects. Because those callers do not own the objects, so the function does not return vector<unique_ptr>.
But this means I need to implement get_objs() like this:
vector<MyObjects*> MyClass::get_objs() const
{
vector<MyObjects*> ret;
for (auto obj : my_objs) {
ret.push_back(obj->get());
}
return ret;
}
My concern is get_objs() is called fairly often, each time there is an overhead to construct this raw pointer vector.
Is there something I could do here? If there is no c++11 tricks to save the overhead, should I just use type vector<MyObject*> for m_objs in the first place?
UPDATE 1
Jonathan Wakely's solution using operator[] improves mine so that caller can access individual object directly.
Is there any other solution? I do not mind go over all the places calling get_objs(), but like to see if there is even better solution.
Another note - I cannot use BOOST, just some restriction I have to live with.
For a start you can use ret.reserve(m_objs.size()) to pre-allocate the right number of elements.
Alternatively, don't return a vector for callers to iterate over directly, but expose a vector-like interface instead:
class MyClass {
public:
struct iterator;
iterator begin();
iterator end();
MyObject* operator[](size_t n) { return m_objs[n].get(); }
private:
vector<unique_ptr<MyObject>> m_objs;
};
This allows the callers to modify the objects directly, rather than getting a container of pointers.
class MyClass {
public:
std::vector<std::unique_ptr<MyObject>> const& get_objs() const {
return m_objs;
}
private:
std::vector<std::unique_ptr<MyObject>> m_objs;
};
a const std::unique_ptr<MyObject>& cannot steal ownership, and is not the same as a std::unique_ptr<const MyObject>. A const std::vector<std::unique_ptr<MyObject>>& can only grant const access to its data.
In c++20 I would instead do this:
class MyClass {
public:
std::span<std::unique_ptr<MyObject> const> get_objs() const {
return {m_objs.begin(), m_objs.end()};
}
private:
std::vector<std::unique_ptr<MyObject>> m_objs;
};
which hides the implementation detail of "I am storing it in a vector" while exposing "I am storing it contiguously".
Prior to c++20, I advise finding or writing your own span type if you have the budget. They are quite useful.
If you can use Boost, try indirect_iterator (http://www.boost.org/doc/libs/1_55_0b1/libs/iterator/doc/indirect_iterator.html). You need to define iterator, begin and end in your class:
typedef boost::indirect_iterator<vector<unique_ptr<MyObject>::iterator> iterator;
iterator begin() { return make_indirect_iterator(m_objs.begin()); }
Then your class exposes iterator, the value of which is reference (not pointer!) to MyObject. You can iterate and access the elements of the vector directly.
For the record, I think something like Jonathan Wakely's answer is the way to go. But since you asked for more possibilities, another one is to use shared_ptr instead of unique_ptr:
class MyClass {
public:
const vector<shared_ptr<MyObject>>& get_objs() const {
return m_objs;
}
private:
vector<shared_ptr<MyObject>> m_objs;
};
This improves the original code in two ways:
There is no longer any need to build up a new vector in get_objs; you can just return a reference to the one you have.
You no longer need to worry about wild pointers in the case where a caller keeps the return value alive longer than the object that returned it--shared_ptr ensures the pointed-to objects aren't deleted until all references have been released.
On another note, get_objs arguably should not be const. Calling code can't modify the vector itself, but it can modify the MyObjects it contains.
Another way is not to return any objects at all and encapsulate how you are storing the data (tell don't ask).
Usually when you get the items you end up iterating through them all, so it makes sense to wrap that up in the class and pass in a function you want your objects to pass through.
The non boost way will be something like
void MyClass::VisitItems(std::function<void, MyObject&> f)
{
for (auto obj : my_objs)
{
f(*obj);
}
}
I have the following problem and I wonder whether there's a better way to solve it:
class myObj {
public:
typedef std::shared_ptr<myObj> handle;
typedef std::shared_ptr<const myObj> const_handle;
int someMethod() { ... }
int someConstMethod() const { ... }
};
Now what I need is a container class that somehow allows you to modify or read a collection of myObj depending on its own constness, like so:
class myCollection {
public:
typedef std::list<myObj::handle> objList;
typedef std::list<myObj::const_handle> const_objList;
inline objList& modify() { return _obl; }
// it would be nice to do this, but it won't compile as
// objList and const_objList are completely different types
inline const_objList& read() const { return _obl; } // doh! compile error...
// returning a const objList won't help either as it would return non-const
// handles, obviously.
// so I am forced to do this, which sucks as i have to create a new list and copy
void read(const_objList &l) {
std::for_each(
_obl.begin(),
_obl.end(),
[&l] (myObj::handle &h) { l.push_back(h); }
// ok as handle can be cast to const_handle
); // for_each
}
private:
objList _obl;
};
So this solution actually works as a const myCollection would only allow you to get a list of const_handle which only allows you to call non-modifying methods of myObj (GOOD).
The problem is that the "read" method is really ugly (BAD).
Another method would be to expose somehow the list methods and return const_handle and handle as needed but it's a lot of overhead, especially if you want to use something more complex than a list.
Any idea?
A list-of-pointers-to-T is not a list-of-pointers-to-constant-T.
std::list<std::shared_ptr<int>> a;
std::list<std::shared_ptr<const int>>& ra = a; // illegal but imagine it's not
std::shared_ptr<const int> x = std::make_shared<const int>(42);
ra.push_back(x); // totally legal, right?
++**a.begin(); // oops... just incremented a const int
Now a list-of-pointers-to-T is, conceptually, a constant-list-of-constant-pointers-to-constant-T, but std::list<std::shared_ptr<T>> does not support such a deep const propagation. const std::list<std::shared_ptr<T>> contains constant pointers to non-constant objects.
You can write your own variant of list<> or your own variant of shared_ptr<> that have such support. It probably won't be very easy though. A const_propagating_shared_ptr is probably the easier of the two. It would have to encapsulate an std::shared_ptr<T> object and forward almost everything to it as-is. As opposed to std::shared_ptr<T> it would have separate const and non-const versions of operator->, operator*() and get().
Given what you stated that you want to accomplish, I don't think that your solution is too bad. Imagine that some other code may be modifying the internal collection, like adding or removing values. Returning a copy of the current state of the collection is safe for client code, since it can work on the copy, without the danger of element being deleted in the meantime. But I digress, this is getting into threading issues and may not be relevant.
You could use prettier:
inline const_objList read() const
{
const_objList cl(_obl.begin(), _obl.end());
return cl;
}
However, I do think that your problems derive from mixing two types of constness: constness of the members of the collection versus the constness of the collection itself.
Instead of Modify and Read methods, that deal with the list as a whole, I would try exposing const and non-const iterators to internal list, through corresponding const and non-const methods returning said iterators.
But this immediately begs the question: why then have myCollection in the first place?
Creating entirely new collection type around std::list doesn't seem needed, unless you get a lot of proverbial bang for the buck from other, added functionality that is not visible in your sample.
You can then make your added functionality free methods that take std::list of your handles as the input. Not everything requires an object and operations on objects need not necessarily be member methods, unless access to private data is required.
You mentioned maybe using another container instead of the list. But your class, as is, won't do it, unless you have a template, where template parameter can be one of STL containers.
Which then implies that you should expose iterators.
Namely, if you foresee changing the internal collection type, you would want to make the public interface to myCollection transparent regarding the collection type. Otherwise, clients will have to recompile each time you change your mind about the internal implementation.
EDIT -----
Finally, if implementing iterators (while interesting and most correct) is too much, why not go for simple getters like in this SO post:
smart pointer const correctness
I'll quote the topmost answer by Rüdiger Stevens (it assumes vector instead of list):
template <typename T>
class MyExample
{
private:
vector<shared_ptr<T> > data;
public:
shared_ptr<const T> get(int idx) const
{
return data[idx];
}
shared_ptr<T> get(int idx)
{
return data[idx];
}
void add(shared_ptr<T> value)
{
data.push_back(value);
}
};
I get an error in a function return statement. I have difficulties with understanding what will I return if the function declaration is :
const vector<Message*>& getMessages(string messageBox) const;
I have class Message, Box and MessageBox:
class Box
{
public:
vector <Message> *messages;
string name;
public:
Box();
~Box();
};
class MessageBox
{
public:
MessageBox();
~MessageBox();
const vector<Message>& getMessages(string messageBox) const;
private:
Box *inbox;
};
Now I'm trying to implement function getMessages. I try to return vector *messages of
Box *inbox. It looks like:
const vector<Message>& MessageBox::getMessages(string messageBox) const
{
if(messageBox == "inbox")
return (const_cast <vector<Message>&>(inbox->messages));
}
This gives me an error mentioned earlier. Maybe, I should change my variables.
Any ideas? Thank you.
Here is your problem. The type of inbox->messages is const std::vector<Messages> *. If you want to return a reference to the value pointed to by inbox->messages, simply reference the pointer:
return *inbox->messages;
There's no need for const_cast at all, because both the source and destination types are already cosnt.
That being said, your code is using an awful lot of pointers needlessly. Why is inbox a pointer? Why not just a value member? Why is messages a pointer to a std::vector instead of just a value?
Your return line should be
return *inbox->messages;
Note that you should also be returning something if messageBox != "inbox". This will be somewhat tricky since you can't legally just return a reference to a temporary local.
Your getMessages function might be better to return std::vector<Message>* since that's how it's held in the class, and it would make it clearer to users of the code that they should take the usual precautions when accessing the pointer (i.e. check for nullptr).
Even better would be to get rid of the raw pointer usage altogether. Favour std::shared_ptr for messages since it's shared between Box and whatever calls getMessages, and favour unique_ptr for Box if its not shared.
You probably don't really need both of these to be pointers, so it would be even simpler to not use pointers at all. Unless you're expecting the size of messages to be large and/or getMessages to be called very frequently, it's not unreasonable and far safer to just return a copy of messages.
My class has a pointer vector:
ptr_vector<Class> vec;
And in some "setup" method adds a few classes to the vector:
void setupOrSomething()
{
vec.push_back(new Class(...));
....
}
Now clients of this class may wish to add their Class objects to this classes list:
void addThingToMyList(Class *cPointer)
{
vec.push_back(cPointer);
}
And they may wish to remove them by passing the same pointer:
void removeThingFromMyList(Class *cPointer) { ... }
Now if I understand correctly, after reading this answer (https://stackoverflow.com/a/357043/48998), I need to implement that method as follows:
void removeThingFromMyList(Class *cPointer)
{
vec.release(std::find_if(vec.begin(),vec.end(),CheckPointerValue(cPointer)).release();
}
struct CheckPointerValue
{
CheckPointerValue(Class* c):cptr(c) {}
bool operator()(Class const& X) { return &X == cptr;}
private:
Class* cptr;
};
I understand I have to also call release() a second time on the auto_ptr that is returned from the ptr_vector.release().
Am I correct in assuming this will ensure that the caller of this method (RemoveThing...) will retain a valid reference to its Class object and that it will not be deleted? I simply want vec to gain a temporary ownership and then relinquish it.
Yes, they will retain a pointer to a valid instance. Of course they need to know that the pointer refers to a valid instance in the first place AND that a pointer to that instance is stored in the vector. If it's not, you will get undefined behavior and probably a seg fault.
I need to store a list of various properties of an object. Property consists of a name and data, which can be of any datatype.
I know I can make a class "Property", and extend it with different PropertySubClasses which only differ with the datatype they are storing, but it does not feel right.
class Property
{
Property(std::string name);
virtual ~Property();
std::string m_name;
};
class PropertyBoolean : Property
{
PropertyBoolean(std::string name, bool data);
bool m_data;
};
class PropertyFloat : Property
{
PropertyFloat(std::string name, float data);
float m_data;
};
class PropertyVector : Property
{
PropertyVector(std::string name, std::vector<float> data);
std::vector<float> m_data;
};
Now I can store all kinds of properties in a
std::vector<Property*>
and to get the data, I can cast the object to the subclass. Or I can make a pure virtual function to do something with the data inside the function without the need of casting.
Anyways, this does not feel right to create these different kind of subclasses which only differ by the data type they are storing. Is there any other convenient way to achieve similar behavior?
I do not have access to Boost.
C++ is a multi-paradigm language. It shines brightest and is most powerful where paradigms are mixed.
class Property
{
public:
Property(const std::string& name) //note: we don't lightly copy strings in C++
: m_name(name) {}
virtual ~Property() {}
private:
std::string m_name;
};
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const std::string& name, const T& data)
: Property(name), m_data(data);
private:
T m_data;
};
typedef std::vector< std::shared_ptr<Property> > property_list_type;
Edit: Why using std::shared_ptr<Property> instead of Property*?
Consider this code:
void f()
{
std::vector<Property*> my_property_list;
for(unsigned int u=0; u<10; ++u)
my_property_list.push_back(new Property(u));
use_property_list(my_property_list);
for(std::vector<Property*>::iterator it=my_property_list.begin();
it!=my_property_list.end(); ++it)
delete *it;
}
That for loop there attempts to cleanup, deleting all the properties in the vector, just before it goes out of scope and takes all the pointers with it.
Now, while this might seem fine for a novice, if you're an only mildly experienced C++ developer, that code should raise alarm bells as soon as you look at it.
The problem is that the call to use_property_list() might throw an exception. If so, the function f() will be left right away. In order to properly cleanup, the destructors for all automatic objects created in f() will be called. That is, my_property_list will be properly destroyed. std::vector's destructor will then nicely cleanup the data it holds. However, it holds pointers, and how should std::vector know whether these pointers are the last ones referencing their objects?
Since it doesn't know, it won't delete the objects, it will only destroy the pointers when it destroys its content, leaving you with objects on the heap that you don't have any pointers to anymore. This is what's called a "leak".
In order to avoid that, you would need to catch all exceptions, clean up the properties, and the rethrow the exception. But then, ten years from now, someone has to add a new feature to the 10MLoC application this has grown to, and, being in a hurry, adds code which leaves that function prematurely when some condition holds. The code is tested and it works and doesn't crash - only the server it's part of now leaks a few bytes an hour, making it crash due to being out of memory about once a week. Finding that makes for many hours of fine debugging.
Bottom line: Never manage resources manually, always wrap them in objects of a class designed to handle exactly one instance of such a resource. For dynamically allocated objects, those handles are called "smart pointer", and the most used one is shared_ptr.
A lower-level way is to use a union
class Property
union {
int int_data;
bool bool_data;
std::cstring* string_data;
};
enum { INT_PROP, BOOL_PROP, STRING_PROP } data_type;
// ... more smarts ...
};
Dunno why your other solution doesn't feel right, so I don't know if this way would feel better to you.
EDIT: Some more code to give an example of usage.
Property car = collection_of_properties.head();
if (car.data_type == Property::INT_PROP) {
printf("The integer property is %d\n", car.int_data);
} // etc.
I'd probably put that sort of logic into a method of the class where possible. You'd also have members such as this constructor to keep the data and type field in sync:
Property::Property(bool value) {
bool_data = value;
data_type = BOOL_PROP;
}
I suggest boost::variant or boost::any. [Related question]
Write a template class Property<T> that derives from Property with a data member of type T
Another possible solution is to write a intermediate class managing the pointers to Property classes:
class Bla {
private:
Property* mp
public:
explicit Bla(Property* p) : mp(p) { }
~Bla() { delete p; }
// The standard copy constructor
// and assignment operator
// aren't sufficient in this case:
// They would only copy the
// pointer mp (shallow copy)
Bla(const Bla* b) : mp(b.mp->clone()) { }
Bla& operator = (Bla b) { // copy'n'swap trick
swap(b);
return *this;
}
void swap(Bla& b) {
using std::swap; // #include <algorithm>
swap(mp, b.mp);
}
Property* operator -> () const {
return mp;
}
Property& operator * () const {
return *mp;
}
};
You have to add a virtual clone method to your classes returning a pointer to a newly created copy of itself:
class StringProperty : public Property {
// ...
public:
// ...
virtual Property* clone() { return new StringProperty(*this); }
// ...
};
Then you'll be able to do this:
std::vector<Bla> v;
v.push_back(Bla(new StringProperty("Name", "Jon Doe")));
// ...
std::vector<Bla>::const_iterator i = v.begin();
(*i)->some_virtual_method();
Leaving the scope of v means that all Blas will be destroyed freeing automatically the pointers they're holding. Due to its overloaded dereferencing and indirection operator the class Bla behaves like an ordinary pointer. In the last line *i returns a reference to a Bla object and using -> means the same as if it was a pointer to a Property object.
A possible drawback of this approach is that you always get a heap operation (a new and a delete) if the intermediate objects must be copied around. This happens for example if you exceed the vector's capacity and all intermediate objects must be copied to a new piece of memory.
In the new standard (i.e. c++0x) you'll be able to use the unique_ptr template: It
can be used inside the standard containers (in contrast to the auto_ptr which must not be used in the standard containers),
offers the usually faster move semantics (it can easily passed around) and
takes care over the held pointers (it frees them automatically).
I see that there are lots of shots at trying to solve your problem by now, but I have a feeling that you're looking in the wrong end - why do you actually want to do this in the first place? Is there some interesting functionality in the base class that you have omitted to specify?
The fact that you'd be forced to switch on a property type id to do what you want with a specific instance is a code smell, especially when the subclasses have absolutely nothing in common via the base class other than a name (which is the type id in this case).
Starting with C++ 17 we have something called as std::variant and std::any.
std::variant
An instance of std::variant at any given time either holds a value of one of its alternative types, or in the case of error - no value.
std::any
The class any describes a type-safe container for single values of any copy constructible type.
An object of class any stores an instance of any type that satisfies the constructor requirements or is empty, and this is referred to as the state of the class any object. The stored instance is called the contained object. Two states are equivalent if they are either both empty or if both are not empty and if the contained objects are equivalent.
The non-member any_cast functions provide type-safe access to the contained object.
You can probably do this with the Boost library, or you could create a class with a type code and a void pointer to the data, but it would mean giving up some of the type safety of C++. In other words, if you have a property "foo", whose value is an integer, and give it a string value instead, the compiler will not find the error for you.
I would recommend revisiting your design, and re-evaluating whether or not you really need so much flexibility. Do you really need to be able to handle properties of any type? If you can narrow it down to just a few types, you may be able to come up with a solution using inheritance or templates, without having to "fight the language".