member function obtains copy of shared pointer to class instance - c++11

I am moving to using C++11 shared pointers.
I need to write member functions that adds pointers to the instance of their class to containers ( i.e. registers ( adds ) their presence in some collection )
Using plain old pointers, I can do this
class myClass {
public:
void Register( std::vector< myClass* >& v_registrants )
{
v_registrants.push_back( this );
}
};
But how to do the same when the collection holds shared pointers? Somehow the member function must obtain a copy of the shared pointer that owns the instance.
I cannot simply create a new shared pointer from this because:
If two shared_ptr are constructed (or made) from the same (non-shared_ptr) pointer, they will both be owning the pointer without sharing it, causing potential access problems when one of them releases it (deleting its managed object) and leaving the other pointing to an invalid location. ( reference )
So, what to do to implement the following class?
class myClass_safe {
public:
void Register( std::vector< std::shared_ptr<myClass_safe > >& v_registrants )
{
//v_registrants.push_back( this ); // compiler freaks out
}
};
As a workaround, I am doing this:
class myClass_safe {
public:
void Register(
std::shared_ptr<myClass_safe >& my_shared_ptr,
std::vector< std::shared_ptr<myClass_safe > >& v_registrants )
{
v_registrants.push_back( my_shared_ptr );
}
};
Which results in this rather strange code
// register the object
object->Register( object, v_registrants );
Is there not something better than this?

I believe this is exactly what std::enable_shared_from_this is intended for.
Inheriting from std::enable_shared_from_this<classname> provides your class with a member function called shared_from_this, that enables you to safely obtain a std::shared_ptr that shares ownership with the original owner.
So to use it, in your case, you would have to change your class definition like this:
class myClass_safe : public std::enable_shared_from_this<myClass_safe> {
public:
void Register( std::vector< std::shared_ptr<myClass_safe > >& v_registrants )
{
v_registrants.push_back( shared_from_this() );
}
};
Note also, that the object must be owned by a shared pointer prior to calling shared_from_this.

Related

C++: convert not from obj1 to obj2, but from obj1* to obj2?

A constructor for MyClass takes a pointer to another such object.
The C++ MyClass is functionally the same as a C "class" based on a typedef'd struct called MyType_T. (The C++ class is basically a wrapper to the old C code.) I'd like to be able to pass in a MyClass* anywhere I could pass in a MyType_T* before.
I'd like to write an automatic conversion of any MyClass* to MyType_T*, but I guess what's throwing me is that my type converter is written to take a MyClass not a MyClass*. Even though I'm sure that's the problem, I can't think of what syntax would solve it. I've thought about making a friend implementation of the cast, but I can't put it before the definition of class MyClass because it won't know the offset of thing. And I can't put after the definition of class MyClass because the MyClass constructor wants to use that conversion.
typedef struct MyStruct {
int iFoo;
struct MyType* ptypeParent;
} MyType_T;
void MyTypeCreator( MyType_T* ptypeSelf, int iFoo_in, MyType_T* ptypeParent );
class MyClass {
public:
MyClass( int iFoo, MyClass* pclassParent ) {
MyTypeCreator( &thing, iFoo, pclassParent ); <--------------- PROBLEM
MyTypeCreator( &thing, iFoo, &pclassParent->thing ); <------- WORKS
};
operator MyType_T*() { return &thing; } <---------------- INCORRECT: attempts to convert MyClass, not MyClass*, to MyType_T*.
MyType_T thing;
};
QUESTION 1: how to write a convertor from MyClass* instead of MyClass?
QUESTION 2: how can such a convertor check for NULL input? (If thing isn't offset of 0, but say 8, then converting from a NULL pclass without a check would give a value of 0x00000008, not NULL...)

How to mock a range-based operator using gmock?

I have a class that inherits from std::map
class LeMap : public std::map<int,int>
{
...
};
I have another class that is supposed to loop over its elments:
class LeMapUser {
LeMap mMap;
public:
void printElements()
{
for( auto& element : mMap ) { whatever(element); }
}
private:
void whatever(int element){ ... }
};
Is it possible to mock LeMap in order to test whatever using gmock ?
Briefly: what operator should I overload to execute the loop?
AFAIK a range-based for loop needs the mMap object to have a begin() member which returns an iterator. The iterator needs to have a post-increment operator to walk along the range. Additionally, mMap must have an end() member, returning a value comparable to the iterator (but not necessarily being an iterator itself).

C++, getting name of the plugin from derived class

I have a requirement wherein, I need to create a base class which will have some pure virtual functions which would be implemented by derived classes. These virtual functions are not enough and I also need to get the name of the plugin to be given to a library from the base class which I will create.
I am using factory pattern. Basically thought that based on the plugin name I would create the instance of that particular derived class.
But, the problem here is since I am using factory pattern, until I send plugin name I would not create object and until object is created plugin name would not be known. Because of this I always see empty plugin name.
Many plugins would be derived from this common base class, it's important to know name of the plugin at runtime.
Please suggest
You need to register a factory for each plugin type in your central factory.
struct common_args {
int width; // whatever
};
struct BasePlugin {
virtual ~BasePlugin() {}
virtual std::string get_name() const = 0;
virtual void do_stuff() = 0;
};
using single_type_factory = std::function<std::unique_ptr<BasePlugin>( common_args ) >;
using plugin_factory = std::function<std::unique_ptr<BasePlugin>( std::string name, common_args ) >;
struct central_factory:plugin_factory {
central_factory(central_factory&&)=delete;
central_factory():
plugin_factory(
[this](std::string name, common_args args)
->std::unique_ptr<BasePlugin>
{
auto it = m_factories.find(name);
if (it == m_factories.end())
return {};
return (*it)(args);
}
)
{}
void register_plugin_type( std::string name, single_type_factory f ) {
m_factories[name] = f;
}
private:
std::unordered_map<std::string, single_type_factory> m_factories;
};
that is just a sketch.

Shared_ptr seems to work on copy, not on original object

I got 2 classes that represent Player and I want to keep in one of them pointer to another one.
So inside my view::Player I create pointer to logic::Player
namespace view {
class Player {
std::shared_ptr<logic::Player> m_player;
//logic::Player* m_player;
public:
void create(logic::Player& player) {
m_player = std::make_shared<logic::Player>(player);
//m_player = &player;
}
};
}
view::Player is created in view::GameState and simply initialised like this
m_playerOneView.create(m_game.getActivePlayer());
m_game is logic::Game object
logic::Game has std::vector<logic::Player>, and public method that returns active one
logic::Player& logic::Game::getActivePlayer() {
return m_players[m_activePlayer];
}
And finnaly
namespace logic {
class Player {
std::string m_name;
int position;
};
}
Now I need original object of logic::Player pointed by std::shared_ptr in my view::Player class. I could simply do that by changing that to raw pointer and it works then (2 commented lines do what I want to achieve basicly). But when I try to do this on std::shared_ptr, I seem to work on copy of logic::Player, because when I update his position for example, it changes everywhere in the game but not in view::Player. How to do that using std::shared_ptr then?

adding a shared_ptr object on a weak_ptr container

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);

Resources