OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

The way to filter objects by type in the factory

  • Thread starter Thread starter Andrii
  • Start date Start date
A

Andrii

Guest
I have the factory that contains a map with the names of objects as key and pointer to function as value

Code:
template<class T>
static T* makeObj()
{
    return new T();
}

using createFunction = std::function<void*()>;
map<std::string, createFunction> types;

template<class T>
static void add(const std::string& name)
{
    types.insert(name, makeObj<T>);
}

I want to add an additional function to get a filtered list of types (get the list of inherited classes), something like this:

Code:
template<class baseType>
static std::list<std::string> getFilteredListOfTypes()
{
}

The question is how to do it. The first idea is to create a map with struct as a value and store an object of the appropriate type there, I can use dynamic_cast and check all types, but I doubt that creating an object is a good idea. Another way is to use std::is_base_of:

Code:
template< class Base, class Derived >
struct is_base_of;

is_base_of take two types, class Base I can get from my getFilteredListOfTypes, but how to get class Derived? Create an object and use decltype... but again here an object is created.

Is there a way to create such a filter function without creating objects? Is it a bad idea to create an object here? Is it a bad idea to create an object for each item of map? I am a little scared of a situation where the factory will have hundreds of totally not small types.

UPD AppFactory.h:

Code:
class AppFactory
{
public:
    template<class T>
    static T* makeObj()
    {
        return new T();
    }

    using createFunction = std::function<void*()>;
    using registerMap = tsl::robin_map<std::string, createFunction>;

    static registerMap& get();

    template<class T>
    static std::unique_ptr<T> createUnique(const std::string& name)
    {
        return std::unique_ptr<T>(create<T>(name));
    }

    template<class T>
    static std::shared_ptr<T> createShared(const std::string& name)
    {
        return std::shared_ptr<T>(create<T>(name));
    }

    template<class T>
    static T* create(const std::string& name)
    {
        if(get().contains(name))
        {
            return static_cast<T*>(get()[name]());
        }
        return nullptr;
    }

    template<class T>
    static bool add(const std::string& name)
    {
        auto resultPair = get().insert_or_assign(name, makeObj<T>);
        return resultPair.second;
    }
};

#define APPFACTORY_ADD(classname) \
namespace { static bool addName = AppFactory::add<classname>(#classname); }

AppFactory.cpp:

Code:
AppFactory::registerMap& AppFactory::get()
{
    static AppFactory::registerMap map;
    return map;
}

Usage of factory:

Code:
...
APPFACTORY_ADD(SomeClass);
...
AppFactory::createUnique<SomeBaseClass>("SomeClass")
...

UPD 2 test implementation of getFilteredListOfTypes

Code:
struct typedata
{
    createFunction func;
    Object* obj;
};
using registerMap = tsl::robin_map<std::string, typedata>;
...
template<class T>
static bool add(const std::string& name)
{
    typedata data;
    data.func = makeObj<T>;
    data.obj = new T();
    auto resultPair = get().insert_or_assign(name, data);
    return resultPair.second;
}
...
template<class BaseType>
static std::list<std::string> getFilteredListOfTypes()
{
    std::list<std::string> typeList;
    for(auto it = get().begin(); it != get().end(); ++it)
    {
        if(dynamic_cast<BaseType*>(get()[it->first].obj))
        {
            typeList.push_back(it->first);
        }
    }
    return typeList;
}

Usage of getFilteredListOfTypes

Code:
class A : public Object
...
class B : public A
...
class C : public B
...
class D : public C
...
class E : public B
...
lst = AppFactory::getFilteredListOfTypes<A>(); // lst -> {"A", "B", "C", "D", "E"}
lst = AppFactory::getFilteredListOfTypes<B>(); // lst -> {"B", "C", "D", "E"}
lst = AppFactory::getFilteredListOfTypes<C>(); // lst -> {"C", "D"}
lst = AppFactory::getFilteredListOfTypes<D>(); // lst -> {"D"}
Continue reading...
 

Latest posts

Online statistics

Members online
0
Guests online
6
Total visitors
6
Top