I am using a library which offers a function foo(Widget*).
My Widgets are stored in
struct WidgetManager {
std::map<int, Widget> dict;
??? getWidget(int id);
}
Originally I stored (raw) Widget pointers in the std::map just because it was convenient to pass them to foo.
If I want to store the actual Widgets in the map, what should the return type of getWidget be so that I can pass a pointer of the Widget to foo?
I am compelled to make it of type iterator, but I don't like that I have to access itr->second to get the Widget(pointer).
You can use & just before you pass your widget to the foo(Widget*) function to get a pointer to it.
struct WidgetManager {
std::map<int, Widget> dict;
Widget& getWidget(int id);
}
usage
WidgetManager wm;
//...
Widget& w = wm.getWidget(id);
foo(&w);
//...
Related
In my class, I have a tuple object which I want to access the objects of in that as reference.
Actually, I want to know how can I write a get function to access the objects in my tuple?
I wrote a function which return the lvalue of my object in the tuple. I want to know how can I change it to return rvalue?
I have a template named GetIndex, which returns the index of type object in my tuple. In my tuple I definitely sure there are unique types object.
//return just lvalue
template <typename T>
T get_module()
{
return std::get<Private::GetIndex<T, Args...>::value>(types);
}
//compilation error
template <typename T>
T& get_module()
{
return &std::get<Private::GetIndex<T, Args...>::value>(types);
}
'''
You can just put & after T. It will be enough.
template <typename T>
T &get_module()
{
return std::get<Private::GetIndex<T, Args...>::value>(types);
}
My class is based on boost::asio tutorial.
This class has a private ctor, is derived from enable_shared_from_this.
its static member function return a shared_ptr from the object created.
I want to store those pointers on a list of weak_ptr, so the list don't need to worry about its life time, either prolong it.
The caller tcp_serve instantiate tcp_connection with create method:
tcp_server:
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.get_io_service());
tcp_connection:
PUBLIC:
typedef boost::shared_ptr<tcp_connection> pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new tcp_connection(io_service));
}
PRIVATE:
tcp_connection(boost::asio::io_service& io_service)
: _socket(io_service), _timer(io_service)
{
}
I am trying to create a list on the tcp_server, I tried many different kind of types, but I can't rightly added the object to the list:
std::list<std::weak_ptr<tcp_connection>> connections;
connections.push_back(new_connection);
kernel/include/linux/types.h
.....
struct list_head {
struct list_head *next, *prev;
};
struct hlist_head {
struct hlist_node *first;
};
struct hlist_node {
struct hlist_node *next, **pprev;
};
What purpose these lists containing no data serve?
These are generic lists that can be used to link any data structure. Say for example, I have a structure
strut my_data {
type1;
type2;
...
struct list_head list;
...
typen;
};
And I have another list head,
struct list_head head;
I am initializing it to reference itself
INIT_LIST_HEAD(&head);
Now I can add an element to it
list_add_tail(&my_data.list, &head);
And the structure is linked now, to get the element back, we can use the list_entry API, which will internally call container_of function. There are other useful APIs used to loop through the list and perform operation, which can be found along with their implementation in kernel/include/list.h.
I have something like this:
enum EFood{
eMeat,
eFruit
};
class Food{
};
class Meat: public Food{
void someMeatFunction();
};
class Fruit: public Food{
void someFruitFunction();
};
class FoodFactory{
vector<Food*> allTheFood;
Food* createFood(EFood foodType){
Food* food=NULL;
switch(foodType){
case eMeat:
food = new Meat();
break;
case eFruit:
food = new Fruit();
break;
}
if(food)
allTheFood.push_back(food);
return food;
}
};
int foo(){
Fruit* fruit = dynamic_cast<Fruit*>(myFoodFactory->createFood(eFruit));
if(fruit)
fruit->someFruitFunction();
}
now I want to change my application to use boost shared_ptr and weak_ptr such that i can delete my food instance in a single place. it would look like this:
class FoodFactory{
vector<shared_ptr<Food> > allTheFood;
weak_ptr<Food> createFood(EFood foodType){
Food* food=NULL;
switch(foodType){
case eMeat:
food = new Meat();
break;
case eFruit:
food = new Fruit();
break;
}
shared_ptr<Food> ptr(food);
allTheFood.push_back(ptr);
return weak_ptr<Food>(ptr);
}
};
int foo(){
weak_ptr<Fruit> fruit = dynamic_cast<weak_ptr<Fruit> >(myFoodFactory->createFood(eFruit));
if(shared_ptr<Fruit> fruitPtr = fruit.lock())
fruitPtr->someFruitFunction();
}
but the problem is that the dynamic_cast doesn't seem to work with weak_ptr
how do I get a weak_ptr<Fruit> out of a weak_ptr<Food> if i know that the object it points to is of derived type?
Direct casting from weak_ptr<A> to weak_ptr<B> will surely don't work, I think you have to convert it to a shared_ptr and then use the casting functionality of shared_ptr:
weak_ptr<Food> food = myFoodFactory->createFood(eFruit)
weak_ptr<Fruit> fruit = weak_ptr<Fruit>(dynamic_pointer_cast<Fruit>(food.lock());
You cannot use dynamic_cast with shared_ptr because it would require to change the template of the object. What in fact you want to do is a dynamic_cast on the internal pointer. To do this you could do a dynamic_cast on the pointer returned by get but that would not be so clean because the reference would not be shared(irrelevant in your case since you're using weak_ptr but relevant when using shared_ptr) and creating a share_ptr on this would be undefined resulting on a double delete.
Use dynamic_pointer_cast to do this but the two types still need to be related. In other words dynamic_cast<T*>(r.get()) needs to be well formed.
you can use BOOST_DISABLE_THREADS to improve performance if you're not bound to multithreading, see https://stackoverflow.com/a/8966130/1067933
I'm using ptr_map from boost for storing objects derived from some base abstract type.
class Entity { virtual void foo() = 0; };
class Entity1 : public Entity {};
class Entity2 : public Entity {};
boost::ptr_map<string, Entity> someMap; // We could store pointers for abstract type
Inserting works great:
someMap.insert("someKey", new Entity1());
someMap.insert("someKey", new Entity2());
But not returning from map:
template<typename EntityType>
EntityType *GetEntity(const string &entityName)
{
return dynamic_cast<EntityType*>(&someMap[entityName]);
}
GetEntity<Entity1>(entityName);
Now the problem: operator[] of ptr_map returns reference! So in constructur there could be calling type from value.
Now compiler fails with error:
instantiated from ‘EntityType* EntityManager::GetEntity(const std::string&) [with EntityType = Entity1, std::string = std::basic_string<char>]’
error: cannot allocate an object of abstract type ‘Entity’
If there is any method in ptr_map which returns pointer to the value, there woudln't be any problems. What could you say about this?
An oft forgotten fact is that operator[] will instantiate the key if it doesn't exist. This is a problem in your case because the key is abstract.
So instead, use at().
That is,
return dynamic_cast<EntityType*>(&someMap.at(entityName));
For more info, read the "Semantics: lookup" section
BTW, I would question your design decision to expose raw pointers stored within container whose very purpose is to alleviate memory management.