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.
Related
I am currently trying to make a Hash table template function and then adapt a password server class on top of it. I've run into a problem when trying to adapt the password server class to the hash table template. When I try to call a function from the template:
PassServer::PassServer(size_t size) : passwords(size)
{
HashTable<std::string, std::string>::HashTable(size);
}
it keeps giving me an error "Qualified name refers into a specialization of variable template 'HashTable'" and I have no idea how to solve this. I've added a specialization for the constructor yet it doesn't seem to change anything. This is the constructor I'm trying to adapt:
template <typename K, typename V>
HashTable<K, V>::HashTable(size_t size = 101)
{
theHash.resize(prime_below(size));
currentSize = 0;
}
with the specialized constructor:
template<>
HashTable<std::string, std::string>::HashTable(size_t size = 101)
{
theHash.resize(prime_below(size));
currentSize = 0;
}
but it still gives the same error
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?
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.
I am dealing with following problem. To be formal I am using VS2010 Ultimate and I try to write an windows forms application, but I get specified error:
1>f:\baza danych\baza\baza\Form5.h(475): error C2664: 'Bazadanych::Dodaj1' : cannot convert parameter 1 from 'Car' to 'Car'
1> Cannot copy construct class 'Car' due to ambiguous copy constructors or no available copy constructor
and here are Car.h where I have declaration of this class
public ref class Car
{
public:
String^ category;
String^ model;
String^ rocznik;
String^ cena;
Car(){};
Car(String^ ,String^ ,String^ );
void edytuj(String^ ,String^ ,String^ );
String^ getmodel(){return this->model;};
String^ getrocznik(){return this->rocznik;};
String^ getcena(){return this->cena;};
virtual String^ getcat()
{
this->category="To rent";
return this->category;
};`
}
Definition:
Car::Car(String^ model1,String^ rocznik1,String^ cena1)
{
this->model=model1;
this->rocznik=rocznik1;
this->cena=cena1;
};
void Car::edytuj(String^ model1,String^ rocznik1,String^ cena1)
{
this->model=model1;
this->rocznik=rocznik1;
this->cena=cena1;
};
Declaration of class where method mentioned in error is:
public ref class Bazadanych
{
public:
cliext::list<Car^> Bazatorent;
cliext::list<Rented^> Bazarented;
cliext::list<Unavaible^> Bazaunavaible;
cliext::list<Car^>::iterator it1;
cliext::list<Rented^>::iterator it2;
cliext::list<Unavaible^>::iterator it3;
Bazadanych()
{
it1=Bazatorent.begin();
it2=Bazarented.begin();
it3=Bazaunavaible.begin();
};
bool Empty();
void Dodaj1(Car);
void Dodaj2(Rented);
void Dodaj3(Unavaible);
void Usun1(Car);
void Usun2(Rented);
void Usun3(Unavaible);
void Czysc();
};
and definition:
void Bazadanych::Dodaj1(Car Element)
{
this->Bazatorent.push_back(Element);
};
I have definitions and declarations in separatly .h and .cpp files. For other methods "Dodaj" and "Usun" I have exactly the same problems. If it could help the class Car is base class for class Rented and Unavaible.
I am pretty new in C++/CLI, so I will be very grateful if someone could help me.
I find the error message strange given that it's a managed class. But you can solve it by changing the method's signature to:
void Bazadanych::Dodaj1(Car^ Element) // notice the "^"
Same for the other similar methods.
I'm guessing that without the hat (^), the compiler treats the variable as a regular C++ class, and therefore requires a copy constructor for it, even though managed classes don't even have copy constructors (you can write them but they're never called implicitly like for regular C++ classes).
EDIT: About the error in your comment: Instead of instantiating the class like this:
Car car;
Do it like this:
Car^ car = gcnew Car();
It says what it means: you have no copy constructor for Car. It might look like this:
Car::Car(const Car& c) {
/* your code here*/
};
Some background here and here.
I am a bit confused on how to marshal below mentioned C++ object to c++/CLI. Could you give me some idea?
Native C++ Classes
class HeaderMessage {
double timestamp;
string ric_code;
}
class TradeMessage {
double price;
int size;
}
class RFARecord
{
public:
RFARecord();
HeaderMessage * hMsg;
list<TradeMessage *> qMsgs;
};
My C++/CLI classes look like this
public ref class RFARecordRef
{
public:
RFARecordRef();
RFARecordRef(RFARecord *record);
HeaderMessageRef hMsg;
List<TradeMessageRef> tMsgs;
private:
RFARecord *record;
};
ref class HeaderMessageRef
{
private:
HeaderMessage *hMsg;
public:
HeaderMessageRef(void);
};
ref class TradeMessageRef
{
private:
TradeMessage *tMsg;
public:
TradeMessageRef(void);
};
I am not sure if my approach is correct.
I read data from a text file and transfer this data in the form of RFARecords to my C# program.
What is the right way to wrap or marshal above data objects to C++/CLI which can then be consumed by my C# program.
Thanks in advance.
Regards,
Alok
If I understand correctly. Your biggest task is going to be marshaling the strings from c++ strings into System::String^ objects.
What your going to do is declare a method in the C++/CLI class that returns a type System::String^ like so:
System::String^ get_str_from_cpp()
{
std::string str = ptr_to_native_cpp_class->get_str();
System::String^ ret_str = std_str2sys_str(str);
return ret_str;
}
The std_str2sys_str method looks like so.
static System::String^ std_str2sys_str(std::string std_str)
{
System::String^ sys_str = gcnew System::String(std_str.c_str());
return sys_str;
}
Of course you could use a char* to if you wanted to.
The "ptr_to_native_cpp_class" variable should be a class variable that points to an instance of your native c++ class. It appears you already have those.
There are also ways to marshal from the System::String^ to std::string or char* which are on the net. Hopefully this example helps though. You don't have to worry about marshalling basic types like ints or bools though, you can just return them directly from your C++/CLI layer to the C#.
To answer the question of marshalling an structure over to C++/CLI; I don't think there is a way to automatically marshal an entire custom structure, even if it is composed completely of basic types. What I do in my code is just write a wrapper object that has specific get methods for each data member like so:
//Native C++ class
class data_container
{
public:
int var1;
int var2;
}
//C++/CLI class
public ref class cli_data_container
{
public:
get_var1() {return data_ptr->var1;}
get_var2() {return data_ptr->var2;}
private:
data_container* data_ptr;
};
If there is an automatic way to do this that would be nice, but we had an intern make these interfaces for us for a few dozen utility classes last summer and they get the job done.