опустить параметр шаблона (для аргумента указателя на функцию)

Я пишу фабрику шаблонов, которая хранит указатель на функцию для создания пользовательских объектов.
Я хотел бы поддержать функцию создания пользователя с аргументом и без аргумента (сейчас подойдет один или нулевой аргумент).
(и я не могу использовать boost или c11, к сожалению)

template< typename T, typename K, typename D >
//T (Type) is a polymorphic type
//K (Key) should have operator < and be copyable
//D (Data argument for creator function) can be copyable
class Factory
{
public:
typedef std::tr1::shared_ptr<T> shared_ptr;
//auto gen Ctor and Dtor

inline void Add( const K& key_, T* (*CreatorFunc)(D) );
inline shared_ptr Create(const K& key_, const D& initData_ ) const;

private:
std::map<K, T* (*)(D) > m_creator;
};

Я был бы рад, если бы пользователь мог использовать это так:

class c1
{
public:
explicit c1(const string& st);
...
};

class c2
{
public:
explicit c2();
...
};

c1* CreateC1(const string& st){ return new c1(st);}
c2* CreateC2(){ return new c2;}

...
//Factory<type, key, arguments>
Factory<c1, int, string> f;
f.Add(0, CreateC1);
f.Create(0, "string Arg");

//Factory<type, key>
Factory<c2, int> f2;
f2.Add(0, CreateC2);
f2.Create(0);

мне удалось заставить это работать с некоторой уродливой специализацией шаблона. Я чувствую, что я иду на это неправильно.

мое решение:

class EmptyClass {};
template< typename T, typename K, typename D = EmptyClass>
class Factory
{
public:
typedef std::tr1::shared_ptr<T> shared_ptr;

inline void Add( const K& key_, T* (*CreatorFunc)(D) );
inline shared_ptr Create(const K& key_, const D& initData_ ) const;

private:
std::map<K, T* (*)(D) > m_creator;
};

template<>
template< typename T, typename K >
class Factory<T, K, EmptyClass >
{
public:
typedef std::tr1::shared_ptr<T> shared_ptr;

inline void Add( const K& key_, T* (*CreatorFunc)() );
inline shared_ptr Create(const K& key_) const;
private:
std::map<K, T* (*)() > m_creator;
};

не стесняйтесь критиковать что-либо еще, если вы хотите

0

Решение

Если вы можете использовать шаблон variadic, возможно, это подойдет вам:

template< typename R, typename K, typename...Args>
class Factory
{
using func_ptr = R*(*)(const Args & ...);
using return_ptr = std::shared_ptr<R>;

public:
inline void Add(const K& key_, func_ptr value);
inline return_ptr Create(const K& key_, Args... initData_) const;

private:
std::map<K, func_ptr> m_creator;
};

Возможная реализация может выглядеть так:

template< typename R, typename K, typename...Args>
class Factory
{
using func_ptr = R*(*)(const Args & ...);
using return_ptr = std::shared_ptr<R>;

public:
inline void Add(const K& key_, func_ptr value)
{
if (value != nullptr)
{
m_creator[key_] = value;
}
}

inline return_ptr Create(const K& key_, Args... initData_) const
{
auto iter = m_creator.find(key_);
if (iter == m_creator.end())
{
return return_ptr(nullptr);
}
return return_ptr(iter->second(initData_...));
}

private:
std::map<K, func_ptr> m_creator;
};
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]