Pretty much the title: Can objects be created based on type_info
? The purpose of this would be to defer the creation of objects. For instance, here's the original "undeferred" code:
Foo* a = new Foo();
Bar* b = new Bar();
And here's the deferred one:
// Store type indices into a vector
std::vector<std::type_index> types;
types.push_back(std::type_index(typeid(Foo)));
types.push_back(std::type_index(typeid(Bar)));
// Iterate through vector, create objects? Is it possible?
If this is not possible, is there any other way to "defer" the construction of objects?
In c++ there is no equivalent of creating objects based on runtime-known types. Languages such as C# and Java can do this precisely because of their extensive reflection support, which is mostly lacking in c++.
One interesting side effect of all this is that c++ developers are never able to slide into the tempting area of reflecting everything. Because of the sheer convenience of reflection-based development lots of core functionality in enterprise applications built with C# and Java revolves around reflection. I'm thinking in particular of OR/M software and libraries such as AutoMapper for C# which make such extensive use of reflection that the overall performance of applications that use them suffers significantly (speaking from personal experience). It is actually refreshing to me to be prevented from that in c++.
The good news is that plugin architectures are very possible using a double inversion of control architecture. Following is a very simple example showing how a separate dll or so could dynamically register types using basic polymorphism.
#include <string>
#include <list>
#include <unordered_map>
#include <iostream>
// ------------------------------------------------------------
// Host application
class Vehicle
{
public:
virtual ~Vehicle() {} // Allow proper inheritance
virtual void Start() = 0; // Start the vehicle
};
class VehicleFactory
{
public:
virtual ~VehicleFactory() {} // Allow proper inheritance
virtual Vehicle* Create() = 0;
};
class VehicleTypeFactory
{
public:
void RegisterFactory(std::string vehicleType, VehicleFactory* vehicleFactory)
{
_factories.insert(std::pair<std::string, VehicleFactory*>(vehicleType, vehicleFactory));
}
Vehicle* Create(std::string vehicleType)
{
return _factories.at(vehicleType)->Create();
}
std::list<std::string> GetTypes()
{
std::list<std::string> result;
for(auto& item: _factories)
{
result.push_back(item.first);
}
return result;
}
private:
std::unordered_map<std::string, VehicleFactory*> _factories;
};
class Tractor: public Vehicle
{
public:
virtual void Start()
{
std::cout << "Starting Tractor..." << std::endl;
std::cout << "Turning on hydraulics..." << std::endl;
}
};
class TractorFactory: public VehicleFactory
{
public:
virtual Vehicle* Create()
{
return new Tractor();
}
};
// ------------------------------------------------------------
// Plugin library (.dll, .so)
// plugin introduces brand new type of vehicle
class Limousine: public Vehicle
{
public:
virtual void Start()
{
std::cout << "Starting Limousine..." << std::endl;
std::cout << "Turning on limo accessories..." << std::endl;
}
};
class LimousineFactory: public VehicleFactory
{
public:
virtual Vehicle* Create()
{
return new Limousine();
}
};
// ------------------------------------------------------------
// Host startup: register tractor factory
int main()
{
VehicleTypeFactory vehicleTypeFactory;
TractorFactory tractorFactory;
vehicleTypeFactory.RegisterFactory("tractor", &tractorFactory);
// ... load plugin(s) which will register other types of factories
// (
LimousineFactory limousineFactory;
vehicleTypeFactory.RegisterFactory("limousine", &limousineFactory);
// )
// Now create one of each type of vehicle
// and tell it to start itself
for(auto& vehicleType: vehicleTypeFactory.GetTypes())
{
auto vehicle = vehicleTypeFactory.Create(vehicleType);
vehicle->Start();
}
return 0;
}
Expected output:
Starting Limousine...
Turning on limo accessories...
Starting Tractor...
Turning on hydraulics...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With