Шаблон AbstractFactory с boost :: factory, не может найти решение - PullRequest
0 голосов
/ 10 сентября 2018

Я пытаюсь реализовать абстрактный класс фабрики, который использует boost :: factory. Подобно тому, что описывает этот пост, https://meetingcpp.com/blog/items/building-factories-in-cplusplus.html, однако я бы хотел, чтобы фабрика была абстрактной с помощью шаблонов. Я также хотел бы, чтобы абстрактная фабрика была одноэлементной, так что это то, что обеспечивает заголовок Singleton.hh (это обычный шаблон Singleton, ничего особенного).

В идеале, это будет поддерживать любое количество аргументов конструктора для ManufacturedType, однако я просто пытаюсь заставить это работать только с 1 обязательным аргументом конструктора (это легко работает с конструируемым классом по умолчанию, но я не могу получить это работать на 1 аргумент, не говоря уже о «любом» количестве параметров.

Когда я пытаюсь использовать фабрику, вот так:

static RegisterInFactory<Base, Foo, std::string, boost::function<Foo*(std::unique_ptr<Base::Options>)>> registerByName("Foo");

Я получаю следующую ошибку:

boost/1.66.0/include/boost/bind/bind.hpp:249:41: error: no match for call to '(boost::factory<Foo*, void, (boost::factory_alloc_propagation)0u>) (std::unique_ptr<Base::Options>)'
         return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_]);
                                         ^
compilation terminated due to -Wfatal-errors.

Исходный код шаблона:

#include "Singleton.hh"
#include <map>
#include <string>
#include <boost/bind.hpp>
#include <boost/functional/factory.hpp>
#include <boost/function.hpp>

template <
  class T_ManufacturedType,
  typename T_ClassIDKey = std::string,
  typename T_CreateFn = boost::function<typename std::remove_pointer<T_ManufacturedType>::type*()>>
class AbstractFactory : public Singleton<AbstractFactory<T_ManufacturedType, T_ClassIDKey, T_CreateFn>>
{
    friend class Singleton<AbstractFactory>;
    using ManufacturedType = typename std::remove_pointer<T_ManufacturedType>::type;

public:
    static void RegCreateFn(const T_ClassIDKey& f_className, const T_CreateFn&    f_fn)
    {
        m_registry[f_className] = f_fn;
    }

template <typename ...T_Args>
    static T_ManufacturedType* Create(const T_ClassIDKey&  f_className, T_Args&&... f_args)
    {
        const auto iter = m_registry.find(f_className);                             // locate the creation function
        return (m_registry.end() != iter) ? iter->second(std::forward<T_Args>(f_args)...) : nullptr; // invoke the creation function
    }

private:
    AbstractFactory() = default;
    // Use these declarations to prohibit the compiler from manufacturing default methods.
    AbstractFactory(const AbstractFactory&) = delete;
    AbstractFactory& operator=(const AbstractFactory&) = delete;

    static std::map<T_ClassIDKey, T_CreateFn>  m_registry;
};

template <class T_ManufacturedType, typename T_ClassIDKey, typename T_CreateFn>
std::map<T_ClassIDKey, T_CreateFn> __attribute__((init_priority(101))) AbstractFactory<T_ManufacturedType, T_ClassIDKey, T_CreateFn>::m_registry;

template <
  class T_AncestorType,
  class T_ManufacturedType,
  typename T_ClassIDKey = std::string,
  typename T_CreateFn = boost::function<typename std::remove_pointer<T_ManufacturedType>::type*()>>
class RegisterInFactory
{
    using ManufacturedType = typename std::remove_pointer<T_ManufacturedType>::type;

public:
    RegisterInFactory(const T_ClassIDKey&  f_id)
    {
        AbstractFactory<T_AncestorType, T_ClassIDKey, T_CreateFn>::Instance().RegCreateFn(f_id, boost::bind(boost::factory<ManufacturedType*>(), _1));
    }
};
...