While both shared pointers and unique pointers in C++11 allow user defined deleters, they have notable syntax differences, as shown in the below mini example:
#include "pch.h"
#include <memory>
class factory
{
public:
static factory * create() {
return new factory();
}
static void destroy(factory* fp) noexcept{
delete fp;
}
factory(const factory &) = delete;
factory& operator= (const factory &) = delete;
private:
char * p_;
factory() {
p_ = new char[100];
}
~factory() {
delete[] p_;
}
};
int main()
{
typedef void(*fp)(factory*);
auto del = [](factory * p) noexcept {
factory::destroy(p);
};
std::shared_ptr<factory> fsptr1(factory::create(), del);
std::shared_ptr<factory> fsptr2(factory::create(), del);
//notice the syntax is different
std::unique_ptr<factory, fp> ufsptr1(factory::create(), del);
std::unique_ptr<factory, decltype(del)> ufsptr2(factory::create(), del);
return 0;
}
The reason behind this is that the template class for shared pointers is defined as
template< class T > class shared_ptr;
and the template class for unique pointers is defined as
template<class T, class Deleter = std::default_delete<T>> class unique_ptr;
My question is: Is there any reason behind this design decision that the syntax of the two differentiates itself from each other? My naive thinking is that if the template class for shared pointers is made as
template< class T, class Deleter = std::default_delete<T>> class shared_ptr;
it will makes more sense. For one thing, it is consistent with the case of unique pointers, and for another, it won't instantiate when the default deleter is not well formed and the user fails to provide a custom one.
The default std::unique_ptr is only storing one element, the pointer to the data it protects. This is because by default, you want to use the least amount of memory possible. But when you specify a deleter, you need also to store it. So you need to differentiate between the two versions.
See here: https://github.com/llvm-mirror/libcxx/blob/master/include/memory#L2397
The storage is a specific type based on the template types.
But for std::shared_ptr, you don't have this constraint, you already have a counter, you need to allocate a block to store it. So you can make the deletion choice inside the allocation logic instead of outside, at the API level.
See here: https://github.com/llvm-mirror/libcxx/blob/master/include/memory#L3592
The compressed_pair is not in the smart pointer itself, but in the allocated block.
I have numerous objects implementing an interface called ExposesCommands.
class ExposesCommands
{
virtual bool get_command_results(std::string command, std::vector<std::string> &results) = 0;
};
typedef std::unique_ptr<ExposesCommands> ExposesCommands_ptr;
Commands are exposed via a template class:
template <typename T>
class ExposedCommands : public ExposesCommands
{
private:
static std::map<const char*, std::string T::*, cmp_str> exposed_cmds;
public:
virtual bool get_command_results(std::string command, std::vector<std::string> &results);
}
Now, I am trying to add sub-commands. Sub-commands will link to sub-objects that implement the commands. The way I would like to add them is like so:
template <typename T>
class ExposedCommands : public ExposesCommands
{
private:
static std::map<const char*, std::string T::*, cmp_str> exposed_cmds;
static std::map<const char*, std::vector<ExposesCommands_ptr> T::*, cmp_str> exposed_sub_cmds;
public:
virtual bool get_command_results(std::string command, std::vector<std::string> &results) {
auto &it = exposed_cmds.find(command.c_str());
if (it != exposed_cmds.cend()) {
auto x = std::bind(it->second, std::placeholders::_1);
std::string data = x(*((T*)this));
if (data != "") {
results.push_back(data);
}
return true;
}
// else check if in exposed_sub_cmds.
// if so, iterate through vector, call get_command_results
// on remainder of command name for each sub object, adding
// its result to the vector of results.
// return true
//
return false;
}
}
I have objects like this implementing the interface (building of the maps is not shown here):
class ObjectA : public ExposesCommands<ObjectA>
{
public:
std::string cmd_x; // command X
std::string cmd_y; // command Y
}
typedef std::unique_ptr<ObjectA> ObjectA_ptr;
class ObjectB
{
public:
std::string cmd_z; // command Z
std::vector<ObjectA_ptr> my_as; // 'ObjectA' sub commands
}
Unfortunately, this doesn't work because I can't assign a &std::vector<ObjectA_ptr> to a std::vector<ExposesCommands_ptr> T::*.
Is there any way to get around this? Or a better approach to this problem?
To summarize your problem: You have a base class and some derived classes
class Base {
public:
virtual ~Base();
};
class Derived1 : public Base;
class Derived2 : public Base;
You need to store a collection of pointers (for ownership management you chose to use std::unique_ptr, which seems wise) to Derived1 objects in a way that it can be used by code that doesn't know Derived1 exists, and only wants to use properties of Base, but also do not want to lose the property that this specific collection of Base objects actually contains Derived1 objects only. This is a kind of type erasure, as the runtime behaciour of the collection should not depend on whether it stores Base, Derived1 or Derived2 objects (or even a mixture of it, so that property gets erased), yet at compile time, you don't want to write all those ugly downcasts (and you want the compiler to verify you only downcast objects from a container you statically know that it does only contain Derived1 objects). Be aware that if you are going to store pointers to Derived1 in std::unique_ptr<Base>, it is absolutely necessary that Base has a virtual destructor.
I don't know any ready-made solution for this off-hand (it couldn't find something skimming over the Boost libraries tagged Container, too), but I can show you how reach that goal yourself. You need a template, to get different compile-time types (just as std::vector is a template), which internally stores the data in a fixed type. So something like this:
typedef std::unique_ptr<Base> Base_ptr;
template <typename T>
class BaseVector {
public:
const std::vector<Base_ptr> &
as_baseclass_vector() const
{
return backing_;
}
private:
std::vector<Base_ptr> backing_;
};
Note that as_baseclass_vector does return a const reference to the raw vector, because the result must not be used to insert objects of the wrong type (e.g. pointers to Derived2 objects) into a CommandVector instantiated for Derived1. This is only half the way to go, the other half is sadly reimplementing the standard library container concept on this vector-wrapper, along this:
template<typename T>
void CommandVector::push_back(std::unique_ptr<T> obj)
{
backing_.push_back(std::move(obj));
}
or, more importantly and interestingly:
template<typename T>
const T* BaseVector::operator[](size_t index) const
{
return static_cast<T*>(backing_[index]);
}
Note that this operator[] does not return a reference-to-unique_ptr, as it could only return a reference to a unique_ptr<Base>, because that is what is stored in the backing vector. If it created a tempory unique_ptr to T, it would have to remove the ownership from the vector - you definitely would not want that! The result has been declared const, because it returns a copy instead of the usual reference, and modifying the return value (which is now forbidden) does not modify the object in the vector, opposed to what users expect. You would have to reimplement all the other methods (iterators would get quite interesting, but probably can be based on boost::transform_iterator) yourself if you chose to go this route.
I am looking for an intuitive and extensible way to implement factories for subclasses of a given base class in c++. I want to provide such a factory function in a library.The tricky part is that I want said factory to work for user-defined subclasses as well (e.g. having the library's factory function build different subclasses depending on what modules are linked to it). The goal is to have minimal burden/confusion for downstream developers to use the factories.
An example of what I want to do is: given a std::istream, construct and return an object of whatever subclass matches the content, or a null pointer if no matches are found. The global factory would have a signature like:
Base* Factory(std::istream &is){ ... };
I am familiar with prototype factories, but I prefer to avoid the need to make/store prototype objects. A related question is posted here for java: Allowing maximal flexibly/extensibility using a factory.
I am not looking for c++11-specific solutions at the moment, but if they are more elegant I would be happy to learn about those.
I came up with one working solution which I believe is fairly elegant, which I will post as an answer. I can imagine this problem to be fairly common, so I am wondering if anyone knows of better approaches.
EDIT: it seems some clarification is in order...
The idea is for the factory to construct an object of a derived class, without containing the logic to decide which one. To make matters worse, the factory method will end up as part of a library and derived classes may be defined in plugins.
Derived classes must be able to decide for themselves whether or not they are fit for construction, based on the input provided (for example an input file). This decision can be implemented as a predicate that can be used by the factory, as was suggested by several people (great suggestion, by the way!).
If I understand this correctly, we want a factory function that can select which derived class to instantiate based on constructor inputs. This is the most generic solution that I could come up with so far. You specify mapping inputs to organize factory functions, and then you can specify constructor inputs upon factory invocation. I hate to say that the code explains more than I could in words, however I think the example implementations of FactoryGen.h in Base.h and Derived.h are clear enough with the help of comments. I can provide more details if necessary.
FactoryGen.h
#pragma once
#include <map>
#include <tuple>
#include <typeinfo>
//C++11 typename aliasing, doesn't work in visual studio though...
/*
template<typename Base>
using FactoryGen<Base> = FactoryGen<Base,void>;
*/
//Assign unique ids to all classes within this map. Better than typeid(class).hash_code() since there is no computation during run-time.
size_t __CLASS_UID = 0;
template<typename T>
inline size_t __GET_CLASS_UID(){
static const size_t id = __CLASS_UID++;
return id;
}
//These are the common code snippets from the factories and their specializations.
template<typename Base>
struct FactoryGenCommon{
typedef std::pair<void*,size_t> Factory; //A factory is a function pointer and its unique type identifier
//Generates the function pointer type so that I don't have stupid looking typedefs everywhere
template<typename... InArgs>
struct FPInfo{ //stands for "Function Pointer Information"
typedef Base* (*Type)(InArgs...);
};
//Check to see if a Factory is not null and matches it's signature (helps make sure a factory actually takes the specified inputs)
template<typename... InArgs>
static bool isValid(const Factory& factory){
auto maker = factory.first;
if(maker==nullptr) return false;
//we have to check if the Factory will take those inArgs
auto type = factory.second;
auto intype = __GET_CLASS_UID<FPInfo<InArgs...>>();
if(intype != type) return false;
return true;
}
};
//template inputs are the Base type for which the factory returns, and the Args... that will determine how the function pointers are indexed.
template<typename Base, typename... Args>
struct FactoryGen : FactoryGenCommon<Base>{
typedef std::tuple<Args...> Tuple;
typedef std::map<Tuple,Factory> Map; //the Args... are keys to a map of function pointers
inline static Map& get(){
static Map factoryMap;
return factoryMap;
}
template<typename... InArgs>
static void add(void* factory, const Args&... args){
Tuple selTuple = std::make_tuple(args...); //selTuple means Selecting Tuple. This Tuple is the key to the map that gives us a function pointer
get()[selTuple] = Factory(factory,__GET_CLASS_UID<FPInfo<InArgs...>>());
}
template<typename... InArgs>
static Base* make(const Args&... args, const InArgs&... inArgs){
Factory factory = get()[std::make_tuple(args...)];
if(!isValid<InArgs...>(factory)) return nullptr;
return ((FPInfo<InArgs...>::Type)factory.first) (inArgs...);
}
};
//Specialize for factories with no selection mapping
template<typename Base>
struct FactoryGen<Base,void> : FactoryGenCommon<Base>{
inline static Factory& get(){
static Factory factory;
return factory;
}
template<typename... InArgs>
static void add(void* factory){
get() = Factory(factory,__GET_CLASS_UID<FPInfo<InArgs...>>());
}
template<typename... InArgs>
static Base* make(const InArgs&... inArgs){
Factory factory = get();
if(!isValid<InArgs...>(factory)) return nullptr;
return ((FPInfo<InArgs...>::Type)factory.first) (inArgs...);
}
};
//this calls the function "initialize()" function to register each class ONCE with the respective factory (even if a class tries to initialize multiple times)
//this step can probably be circumvented, but I'm not totally sure how
template <class T>
class RegisterInit {
int& count(void) { static int x = 0; return x; } //counts the number of callers per derived
public:
RegisterInit(void) {
if ((count())++ == 0) { //only initialize on the first caller of that class T
T::initialize();
}
}
};
Base.h
#pragma once
#include <map>
#include <string>
#include <iostream>
#include "Procedure.h"
#include "FactoryGen.h"
class Base {
public:
static Base* makeBase(){ return new Base; }
static void initialize(){ FactoryGen<Base,void>::add(Base::makeBase); } //we want this to be the default mapping, specify that it takes void inputs
virtual void speak(){ std::cout << "Base" << std::endl; }
};
RegisterInit<Base> __Base; //calls initialize for Base
Derived.h
#pragma once
#include "Base.h"
class Derived0 : public Base {
private:
std::string speakStr;
public:
Derived0(std::string sayThis){ speakStr=sayThis; }
static Base* make(std::string sayThis){ return new Derived0(sayThis); }
static void initialize(){ FactoryGen<Base,int>::add<std::string>(Derived0::make,0); } //we map to this subclass via int with 0, but specify that it takes a string input
virtual void speak(){ std::cout << speakStr << std::endl; }
};
RegisterInit<Derived0> __d0init; //calls initialize() for Derived0
class Derived1 : public Base {
private:
std::string speakStr;
public:
Derived1(std::string sayThis){ speakStr=sayThis; }
static Base* make(std::string sayThat){ return new Derived0(sayThat); }
static void initialize(){ FactoryGen<Base,int>::add<std::string>(Derived0::make,1); } //we map to this subclass via int with 1, but specify that it takes a string input
virtual void speak(){ std::cout << speakStr << std::endl; }
};
RegisterInit<Derived1> __d1init; //calls initialize() for Derived1
Main.cpp
#include <windows.h> //for Sleep()
#include "Base.h"
#include "Derived.h"
using namespace std;
int main(){
Base* b = FactoryGen<Base,void>::make(); //no mapping, no inputs
Base* d0 = FactoryGen<Base,int>::make<string>(0,"Derived0"); //int mapping, string input
Base* d1 = FactoryGen<Base,int>::make<string>(1,"I am Derived1"); //int mapping, string input
b->speak();
d0->speak();
d1->speak();
cout << "Size of Base: " << sizeof(Base) << endl;
cout << "Size of Derived0: " << sizeof(Derived0) << endl;
Sleep(3000); //Windows & Visual Studio, sry
}
I think this is a pretty flexible/extensible factory library. While the code for it is not very intuitive, I think using it is fairly simple. Of course, my view is biased seeing as I'm the one that wrote it, so please let me know if it is the contrary.
EDIT : Cleaned up the FactoryGen.h file. This is probably my last update, however this has been a fun exercise.
My comments were probably not very clear. So here is a C++11 "solution" relying on template meta programming : (Possibly not the nicest way of doing this though)
#include <iostream>
#include <utility>
// Type list stuff: (perhaps use an existing library here)
class EmptyType {};
template<class T1, class T2 = EmptyType>
struct TypeList
{
typedef T1 Head;
typedef T2 Tail;
};
template<class... Etc>
struct MakeTypeList;
template <class Head>
struct MakeTypeList<Head>
{
typedef TypeList<Head> Type;
};
template <class Head, class... Etc>
struct MakeTypeList<Head, Etc...>
{
typedef TypeList<Head, typename MakeTypeList<Etc...>::Type > Type;
};
// Calling produce
template<class TList, class BaseType>
struct Producer;
template<class BaseType>
struct Producer<EmptyType, BaseType>
{
template<class... Args>
static BaseType* Produce(Args... args)
{
return nullptr;
}
};
template<class Head, class Tail, class BaseType>
struct Producer<TypeList<Head, Tail>, BaseType>
{
template<class... Args>
static BaseType* Produce(Args... args)
{
BaseType* b = Head::Produce(args...);
if(b != nullptr)
return b;
return Producer<Tail, BaseType>::Produce(args...);
}
};
// Generic AbstractFactory:
template<class BaseType, class Types>
struct AbstractFactory {
typedef Producer<Types, BaseType> ProducerType;
template<class... Args>
static BaseType* Produce(Args... args)
{
return ProducerType::Produce(args...);
}
};
class Base {}; // Example base class you had
struct Derived0 : public Base { // Example derived class you had
Derived0() = default;
static Base* Produce(int value)
{
if(value == 0)
return new Derived0();
return nullptr;
}
};
struct Derived1 : public Base { // Another example class
Derived1() = default;
static Base* Produce(int value)
{
if(value == 1)
return new Derived1();
return nullptr;
}
};
int main()
{
// This will be our abstract factory type:
typedef AbstractFactory<Base, MakeTypeList<Derived0, Derived1>::Type> Factory;
Base* b1 = Factory::Produce(1);
Base* b0 = Factory::Produce(0);
Base* b2 = Factory::Produce(2);
// As expected b2 is nullptr
std::cout << b0 << ", " << b1 << ", " << b2 << std::endl;
}
Advantages:
No (additional) run-time overhead as you would have with the function pointers.
Works for any base type, and for any number of derived types. You still end up calling the functions of course.
Thanks to variadic templates this works with any number of arguments (giving an incorrect number of arguments will produce a compile-time error message).
Explicit registering of the produce member functions
is not required.
Disadvantages:
All of your derived types must be available when you declare the
Factory type. (You must know what the possible derived types are and they must be complete.)
The produce member functions for the derived types must be public.
Can make compilation slower. (As always the case when relying on template metaprogramming)
In the end, using the prototype design pattern might turn out better. I don't know since I haven't tried using my code.
I'd like to state some additional things (after further discussion on the chat):
Each factory can only return a single object. This seems strange, as the users decide whether they will take the input to create their object or not. I would for that reason suggest your factory can return a collection of objects instead.
Be careful not to overcomplicate things. You want a plugin system, but I don't think you really want factories. I would propose you simply make users register their classes (in their shared object), and that you simply pass the arguments to the classes' Produce (static) member functions. You store the objects if and only if they're not the nullptr.
Update: This answer made the assumption that some kind of magic existed that could be read and passed to the factory, but that's apparently not the case. I'm leaving the answer here because a) I may update it, and b) I like it anyway.
Not hugely different from your own answer, not using C++11 techniques (I've not had a chance to update it yet, or have it return a smart pointer, etc), and not entirely my own work, but this is the factory class I use. Importantly (IMHO) it doesn't call each possible class's methods to find the one that matches - it does this via the map.
#include <map>
// extraneous code has been removed, such as empty constructors, ...
template <typename _Key, typename _Base, typename _Pred = std::less<_Key> >
class Factory {
public:
typedef _Base* (*CreatorFunction) (void);
typedef std::map<_Key, CreatorFunction, _Pred> _mapFactory;
// called statically by all classes that can be created
static _Key Register(_Key idKey, CreatorFunction classCreator) {
get_mapFactory()->insert(std::pair<_Key, CreatorFunction>(idKey, classCreator));
return idKey;
}
// Tries to create instance based on the key
static _Base* Create(_Key idKey) {
_mapFactory::iterator it = get_mapFactory()->find(idKey);
if (it != get_mapFactory()->end()) {
if (it->second) {
return it->second();
}
}
return 0;
}
protected:
static _mapFactory * get_mapFactory() {
static _mapFactory m_sMapFactory;
return &m_sMapFactory;
}
};
To use this you just declare the base-type, and for each class you register it as a static. Note that when you register, the key is returned, so I tend to add this as a member of the class, but it's not necessary, just neat :) ...
// shape.h
// extraneous code has been removed, such as empty constructors, ...
// we also don't technically need the id() method, but it could be handy
// if at a later point you wish to query the type.
class Shape {
public:
virtual std::string id() const = 0;
};
typedef Factory<std::string, Shape> TShapeFactory;
Now we can create a new derived class, and register it as creatable by TShapeFactory...
// cube.h
// extraneous code has been removed, such as empty constructors, ...
class Cube : public Shape {
protected:
static const std::string _id;
public:
static Shape* Create() {return new Cube;}
virtual std::string id() const {return _id;};
};
// cube.cpp
const std::string Cube::_id = TShapeFactory::Register("cube", Cube::Create);
Then we can create a new item based on, in this case, a string:
Shape* a_cube = TShapeFactory::Create("cube");
Shape* a_triangle = TShapeFactory::Create("triangle");
// a_triangle is a null pointer, as we've not registered a "triangle"
The advantage of this method is that if you create a new derived, factory-generatable class, you don't need to change any other code, providing you can see the factory class and derive from the base:
// sphere.h
// extraneous code has been removed, such as empty constructors, ...
class Sphere : public Shape {
protected:
static const std::string _id;
public:
static Shape* Create() {return new Sphere;}
virtual std::string id() const {return _id;};
};
// sphere.cpp
const std::string Sphere::_id = TShapeFactory::Register("sphere", Sphere::Create);
Possible improvements that I'll leave to the reader include adding things like: typedef _Base base_class to Factory, so that when you've declared your custom factory, you can make your classes derive from TShapeFactory::base_class, and so on. The Factory should probably also check if a key already exists, but again... it's left as an exercise.
The best solution I can currently think of is by using a Factory class which stores pointers to producing functions for each derived class. When a new derived class is made, a function pointer to a producing method can be stored in the factory.
Here is some code to illustrate my approach:
#include <iostream>
#include <vector>
class Base{};
// Factory class to produce Base* objects from an int (for simplicity).
// The class uses a list of registered function pointers, which attempt
// to produce a derived class based on the given int.
class Factory{
public:
typedef Base*(*ReadFunPtr)(int);
private:
static vector<ReadFunPtr> registeredFuns;
public:
static void registerPtr(ReadFunPtr ptr){ registeredFuns.push_back(ptr); }
static Base* Produce(int value){
Base *ptr=NULL;
for(vector<ReadFunPtr>::const_iterator I=registeredFuns.begin(),E=registeredFuns.end();I!=E;++I){
ptr=(*I)(value);
if(ptr!=NULL){
return ptr;
}
}
return NULL;
}
};
// initialize vector of funptrs
std::vector<Factory::ReadFunPtr> Factory::registeredFuns=std::vector<Factory::ReadFunPtr>();
// An example Derived class, which can be produced from an int=0.
// The producing method is static to avoid the need for prototype objects.
class Derived : public Base{
private:
static Base* ProduceDerivedFromInt(int value){
if(value==0) return new Derived();
return NULL;
}
public:
Derived(){};
// registrar is a friend because we made the producing function private
// this is not necessary, may be desirable (e.g. encapsulation)
friend class DerivedRegistrar;
};
// Register Derived in the Factory so it will attempt to construct objects.
// This is done by adding the function pointer Derived::ProduceDerivedFromInt
// in the Factory's list of registered functions.
struct DerivedRegistrar{
DerivedRegistrar(){
Factory::registerPtr(&(Derived::ProduceDerivedFromInt));
}
} derivedregistrar;
int main(){
// attempt to produce a Derived object from 1: should fail
Base* test=Factory::Produce(1);
std::cout << test << std::endl; // outputs 0
// attempt to produce a Derived object from 0: works
test=Factory::Produce(0);
std::cout << test << std::endl; // outputs an address
}
TL;DR: in this approach, downstream developers need to implement the producing function of a derived class as a static member function (or a non-member function) and register it in the factory using a simple struct.
This seems simple enough and does not require any prototype objects.
Here is a sustainable idiom for managing factories that resolve at runtime. I've used this in the past to support fairly sophisticated behavior. I favor simplicity and maintainability without giving up much in the way of functionality.
TLDR:
Avoid static initialization in general
Avoid "auto-loading" techniques like the plague
Communicate ownership of objects AND factories
Separate usage and factory management concerns
Using Runtime Factories
Here is the base interface that users of this factory system will interact with. They shouldn't need to worry about the details of the factory.
class BaseObject {
public:
virtual ~BaseObject() {}
};
BaseObject* CreateObjectFromStream(std::istream& is);
As an aside, I would recommend using references, boost::optional, or shared_ptr instead of raw pointers. In a perfect world, the interface should tell me who owns this object. As a user, am I responsible for deleting this pointer when it's given to me? It's painfully clear when it's a shared_ptr.
Implementing Runtime Factories
In another header, put the details of managing the scope of when the factories are active.
class RuntimeFactory {
public:
virtual BaseObject* create(std::istream& is) = 0;
};
void RegisterRuntimeFactory(RuntimeFactory* factory);
void UnregisterRuntimeFactory(RuntimeFactory* factory);
I think the salient point in all of this is that usage is a different concern from how the factories are initialized and used.
We should note that the callers of these free functions own the factories. The registry does not own them.
This isn't strictly necessary, though it offers more control when and where these factories get destroyed. The point where it matters is when you see things like "post-create" or "pre-destroy" calls. Factory methods with these sorts of names are design smells for ownership inversion.
Writing another wrapper around this to manage the factories life-time would be simple enough anyway. It also lends to composition, which is better.
Registering Your New Factory
Write wrappers for each factory registration. I usually put each factory registration in its own header. These headers are usually just two function calls.
void RegisterFooFactory();
void UnregisterFooFactory();
This may seem like overkill, but this sort of diligence keeps your compile times down.
My main then is reduced to a bunch of register and unregister calls.
#include <foo_register.h>
#include <bar_register.h>
int main(int argc, char* argv[]) {
SetupLogging();
SetupRuntimeFactory();
RegisterFooFactory();
RegisterBarFactory();
// do work...
UnregisterFooFactory();
UnregisterBarFactory();
CleanupLogging();
return 0;
}
Avoid Static Init Pitfalls
This specifically avoids objects created during static loading like some of the other solutions. This is not an accident.
The C++ spec won't give you useful assurances about when static loading will occur
You'll get a stack trace when something goes wrong
The code is simple, direct, easy to follow
Implementing the Registry
Implementation details are fairly mundane, as you'd imagine.
class RuntimeFactoryRegistry {
public:
void registerFactory(RuntimeFactory* factory) {
factories.insert(factory);
}
void unregisterFactory(RuntimeFactory* factory) {
factories.erase(factory);
}
BaseObject* create(std::istream& is) {
std::set<RuntimeFactory*>::iterator cur = factories.begin();
std::set<RuntimeFactory*>::iterator end = factories.end();
for (; cur != end; cur++) {
// reset input?
if (BaseObject* obj = (*cur)->create(is)) {
return obj;
}
}
return 0;
}
private:
std::set<RuntimeFactory*> factories;
};
This assumes that all factories are mutually exclusive. Relaxing this assumption is unlikely to result in well-behaving software. I'd probably make stronger claims in person, hehe. Another alternative would be to return a list of objects.
The below implementation is static for simplicity of demonstration. This can be a problem for multi-threaded environments. It doesn't have to be static, nor do I recommend it should or shouldn't be static, it just is here. It isn't really the subject of the discussion, so I'll leave it at that.
These free functions only act as pass-through functions for this implementation. This lets you unit test the registry or reuse it if you were so inclined.
namespace {
static RuntimeFactoryRegistry* registry = 0;
} // anon
void SetupRuntimeFactory() {
registry = new RuntimeFactoryRegistry;
}
void CleanupRuntimeFactory() {
delete registry;
registry = 0;
}
BaseObject* CreateObjectFromStream(std::istream& is) {
return registry->create(is);
}
void RegisterRuntimeFactory(RuntimeFactory* factory) {
registry->registerFactory(factory);
}
void UnregisterRuntimeFactory(RuntimeFactory* factory) {
registry->unregisterFactory(factory);
}
First, there's not really enough detail here to form an opinion, so I'm left to guess. You've provided a challenging question and a minimal solution, but not clarified what is wrong with your solution.
I suspect the complaint centers around the reset back to knowing nothing between a refused construction and the following construction attempts. Given a very large number of potential factories this reset could have us parsing the same data hundreds or thousands of times. If this is the problem the question is this: how do you structure the predicate evaluation phase to limit the amount of work, and allow it to reuse previous parsing results.
I suggest having each factory register with:
1) a factory builder function taking the specialization parameter(s) (iostream in the example)
2) an unordered set of boolean predicates
3) required boolean values of each predicate to allow construction
The set of predicates is used to create/modify the predicate tree. Interior nodes in the tree represent predicates (branching to 'pass', 'fail', and possibly 'don't care'). Both interior nodes and leaves hold constructors which are satisfied if the ancestral predicates are satisfied. As you traverse the tree you first look for constructors at the current level, then evaluate the predicate and follow the required path. If no solution is found along that child path the follow the 'don't care' path.
This allows new factories to share predicate functions. There's probably lots of questions about managing/sorting the tree when the factories go on/off line. There's also the possibility of parser state data that needs to be retained across predicates and reset when construction is completed. There's lots of open questions, but this may work toward addressing the perceived problems with your solution.
TL:DR; Create a graph of predicates to traverse when attempting construction.
Simple solution is just a switch-case:
Base *create(int type, std::string data) {
switch(type) {
case 0: return new Derived1(data);
case 1: return new Derived2(data);
};
}
But then it's just deciding which type you want:
int type_of_obj(string s) {
int type = -1;
if (isderived1(s)) type=0;
if (isderived2(s)) type=1;
return type;
}
Then it's just connecting the two:
Base *create_obj(string s, string data,
Base *(*fptr)(int type, string data),
int (*fptr2)(string s))
{
int type = fptr2(s);
if (type==-1) return 0;
return fptr(type, data);
}
Then it's just registering the function pointers:
class Registry {
public:
void push_back(Base* (*fptr)(int type, string data),
int (*fptr2)(string s));
Base *create(string s, string data);
};
The plugin will have the 2 functions, and the following:
void register_classes(Registry ®) {
reg.push_back(&create, &type_of_obj);
...
}
Plugin loader will dlopen/dlsym the register_classes functions.
(on the other hand, I'm not using this kind of plugins myself because creating new plugins is too much work. I have better way to provide modularity for my program's pieces. What kills plugins is the fact that you need to modify your build system to create new dll's or shared_libs, and doing that is just too much work - ideally new module is just one class; without anything more complicated build system modifications)
I am trying to make a template class as placeholder class which can hold something like and string and type T object. Below is the code which I have written for the same.
#include <iostream>
#include <string>
#include <map>
using namespace std;
//A class which act as placeholder to hold
//unknown object. Something similar as Object
//in Java
template <typename T>
class Genric
{
public:
map<string, T> addP; //This will be placeholder for time
// being.
};
class A
{
public:
Genric t1; //Have object of Genric class so that we can
// access the member variable in future.
void foo()
{
cout<<"Calling foo"<<endl;
}
};
int main()
{
A a1;
a1.foo();
}
But when I tried to compile I am getting below error.
$ g++ tempClass.cxx
tempClass.cxx:21:9: error: invalid use of template-name 'Genric' without an argument list
The purpose of above Genric class is just to act as placeholder class for one of the member variables which can be populated in future.
So is there a way we can write such Genric class.
You are defining Genric as a template class, but then trying to initialize t1 without giving a type to it. That is the error you are getting. Try for example:
Genric<int> t1;
Or, if you are looking for a truly runtime generic, look into boost::any.
You need something like boost::any:
map<string, boost::any> anywayzz;
You can store any object in it. You don't need Genric class template.
If you're not using boost, then you can implement any yourself. Look for its implementation, or type-erasure, on this site. You will surely get some idea. Start from here:
Type erasure techniques
A template is "generic" until the program is compiled. At that point the compile must be made aware of what types it has to deal with.
If you want something that can contain a compile-time unknown (better: not yet known) type template are not the solution. Since the actual type will be known just at runtime, you have to go towards runtime-based polymorphism (inheritance from a polymorphic base) eventually wrapped inside an "handler".
In essence you need a base with at leas t a virtual function that allow you to check the type, and generic derived class that implement that function in a suitable way for all types.
boost::any can be an implementation, but there can be simpler ways, especially considering that "a function that allows to discover a runtime type" is no more than ... dynamic_cast.
You can so cometo a solution like this
#include <memory>
class any_value
{
template<class T>
class wrapper; //see below
class common_base
{
public:
virtual ~common_base() {} //this makes the type polymorphic
template<class T>
T* has_value()
{
auto* ptr = dynamic_cast<wrapper<T>*>(this);
return ptr? &ptr->m: nullptr;
}
};
template<class T>
class wrapper: public common_base
{
public:
wrapper() :m() {}
wrapper(const T& t) :m(t) {}
T m;
};
std::unique_ptr<common_base> pb;
public:
any_value() {}
template<class T>
any_value(const T& t) :pb(new wrapper<T>(t)) {}
template<class T>
any_value& operator=(const T& t)
{ pb = std::unique_ptr<common_base>(new wrapper<T>(t)); return *this; }
any_value(any_value&&) =default;
any_value& operator=(any_value&&) =default;
//NOW THE GETTERS
template<class T>
T* get() const //nullptr if not holding a T*
{ return bool(pb)? pb->has_value<T>(): nullptr; }
template<class T>
bool get(T& t)
{
T* pt = get<T>();
if(pt) t = *pt;
return bool(pt);
}
};
#include <iostream>
#include <string>
int main()
{
any_value a(5), b(2.7192818), c(std::string("as a string"));
int vi=0; double vd=0; std::string vs;
if(!a.get(vi)) vi=0; //will go
if(!a.get(vd)) vd=0; //will fail
if(!a.get(vs)) vs.clear(); //will fail
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
if(!b.get(vi)) vi=0; //will fail
if(!b.get(vd)) vd=0; //will go
if(!b.get(vs)) vs.clear(); //will fail
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
if(!c.get(vi)) vi=0; //will fail
if(!c.get(vd)) vd=0; //will fail
if(!c.get(vs)) vs.clear(); //will go
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
}
Following Abhinav comment:
Since the C++ type system is static, you cannot -in general- deserialize an "unknown", unless you first deserialize something that can be "Known".
For this you first need a way to represet a C++ type (not object) into an recognizable value (sort of type-uid), and a "factory" that creates the wrappers appropriated for those "values".
On saving, you just save that uid, then ask via a common_base virtual function to save the wrapped value.
On loading, you first load the uid, than create a new wrapper with appropriate type (see after) and than load the value via a common_base virtual function.
To create an appropriate wrapper, you need a table that maps the uid-s towards functions that create the wrapper associated with the type uid.
This table must be pre-initialized for all the types you need to be able to serialize / deserialize.
But this goes long away your original question, that doesn't speak about serialization/deserialization.
If the problem is "serialization", the "type erasure" is not a complete solution. You should much more look at the "factory pattern". And post another question better suited for that argument.
If I have a polymorphic base class called Base as well as classes Derived1 and Derived2 which inherit from Base. I can then use boost::lambda to create a factory of sorts. Something like:
typedef boost::function<Base *()> Creator;
std::map<std::string,Creator> map1;
map1["Derived1"] = boost::lambda::new_ptr<Derived1>();
map1["Derived2"] = boost::lambda::new_ptr<Derived2>();
(This isn't real code, I'm just trying to illustrate the problem.)
This works, so I can then do a lookup in the map using a string and then invoke the lambda function to instantiate that class. All good.
The problem with this is that it's dealing in raw pointers, I'd prefer to be using smart pointers (std::shared_ptr).
So if I change from:
typedef boost::function<Base *>() Creator;
to:
typedef boost::function<std::shared_ptr<Base> >() Creator;
Then I'm getting stuck from here. I've tried using boost::lambda::bind in conjunction with boost::lambda::new_ptr but I'm not having much luck, can't get past compilation errors. (Huge reams of template-related error output.)
I've checked other similar messages within StackOverflow, Using boost::bind and boost::lambda::new_ptr to return a shared_ptr constructor is close but if I try to apply its solution I get the template errors mentioned above.
I'm happy to provide sample code and the actual errors if it helps, but hopefully the above info is sufficient. I'm using boost 1.47.0 on GCC 4.6 as well as 4.7 snapshot on Fedora 15.
class Base {
public:
virtual ~Base() = 0;
};
Base::~Base() {}
class Derived1 : public Base {};
class Derived2 : public Base {};
typedef boost::shared_ptr<Base> BasePtr;
typedef boost::function<BasePtr()> Creator;
template <typename T>
Creator MakeFactory()
{
namespace la = boost::lambda;
return la::bind(
la::constructor<BasePtr>(),
la::bind(la::new_ptr<T>()));
}
int _tmain(int argc, _TCHAR* argv[])
{
std::map<std::string,Creator> map1;
map1["Derived1"] = MakeFactory<Derived1>();
map1["Derived2"] = MakeFactory<Derived2>();
BasePtr p1 = map1["Derived1"]();
BasePtr p2 = map1["Derived2"]();
return 0;
}
however, why go to the trouble when you could write:
template <typename T>
BasePtr MakeFactoryImpl()
{
return BasePtr(new T());
}
template <typename T>
Creator MakeFactory()
{
return Creator(&MakeFactoryImpl<T>);
}
This is a common problem. The fact that two types are related (in your case by inheritance) does not imply that the instantiations of a template with those two types maintains the same relationship.
The solution is to return always shared_ptr<Base>, since it can hold both pointers to Base or any derived type, which will be semantically compatible with your current version (i.e. in both versions the caller gets a (smart)-pointer-to Base.
As an aside, I would avoid returning shared_ptr from a factory, as you are forcing your choice of smart pointer into all of your users. I would prefer to either return a raw pointer (the user can choose, but it is dangerous in some situations) or a unique_ptr or even auto_ptr, which are safe and still allow the user to choose a different mechanism (i.e. if your function returns an auto_ptr, the user can still use a shared_ptr by doing shared_ptr<Base> p( f().release() );, while the opposite is not possible (memory managed by a shared_ptr cannot be released to use in a different smart pointer.
This quick-and-dirty return type adapter is good not only for converting return types from Derived* to Base*, but between any convertible types. For simplicity, the function-object takes no arguments. With C++11 variadic templates it should be easy to add arbitrary argument handling. Feel free to improve on this in any way you wish.
template <typename ToType>
class return_type_adapter
{
template <typename toType>
class return_type_adapter_impl_base
{
public:
virtual toType call() = 0;
};
template <typename toType, typename Func>
class return_type_adapter_impl : public return_type_adapter_impl_base<toType>
{
public:
return_type_adapter_impl (Func func) : func(func) {}
toType call() { return toType(func()); }
private:
Func func;
};
boost::shared_ptr<return_type_adapter_impl_base<ToType> > impl_base;
public:
ToType operator() () { return impl_base->call(); }
template <typename Func>
return_type_adapter (Func func) :
impl_base(new return_type_adapter_impl<ToType, Func>(func)) {}
};
map1["Derived1"] = boost::lambda::bind(
boost::lambda::constructor<boost::shared_ptr<Base>>(),
boost::lambda::bind(
boost::lambda::new_ptr<Derived1>()));
map1["Derived2"] = boost::lambda::bind(
boost::lambda::constructor<boost::shared_ptr<Base>>(),
boost::lambda::bind(
boost::lambda::new_ptr<Derived2>()));
But honestly, this is the level of complexity where it doesn't really make sense to use boost lambda any more. A simpler solution:
template<typename DerivedType>
boost::shared_ptr<Base> makeDerived() {
return boost::shared_ptr<Base>(new DerivedType);
}
[...]
map1["Derived1"] = makeDerived<Derived1>;
map1["Derived2"] = makeDerived<Derived2>;