Here we have two template classes.
The first one named "Factory", it't a singleton-Factory-Model class and have a template-member-function that is responsible for registering class-producer in this factory.
The second named "FactoryRegister", it's only duty is to register T2 in Factory T1.
In the end, we have a macro that declare a FactoryRegister variable, by using this macro in global scope, we realise that register all classes in factories before our program is running.
#include <memory>
#include <mutex>
#include <map>
#include <string>
template <typename Base>
class Factory {
public:
static std::shared_ptr<Factory<Base> > get_instance() {
static std::shared_ptr<Factory> factory;
if (!factory) {
static std::mutex _new_mutex;
std::lock_guard<std::mutex> guard(_new_mutex);
if (!factory) {
factory.reset(new Factory);
}
}
return factory;
}
template <typename Derived,
typename = typename std::enable_if<std::is_base_of<Base, Derived>::value>::type>
void add(std::string pname) {
std::lock_guard<std::mutex> guard(_mutex);
_producers.emplace(pname, [](std::string name) {return new Derived(name);});
}
void del(std::string pname) {
std::lock_guard<std::mutex> guard(_mutex);
_producers.erase(pname);
}
bool is_exist(std::string pname) {
return _producers.find(pname) != _producers.end();
}
std::shared_ptr<Base> create(std::string pname, std::string name) {
std::shared_ptr<Base> ret;
if (is_exist(pname)) {
ret.reset(_producers[pname](name));
}
return ret;
}
private:
Factory() = default;
Factory(const Factory&) = delete;
Factory& operator=(Factory&) = delete;
private:
std::mutex _mutex;
std::map<std::string, std::function<Base*(std::string)> > _producers;
};
template<typename T1, typename T2>
struct FactoryRegister {
FactoryRegister(std::string name) {
Factory<T1>::get_instance()->add<T2>(name);
}
};
#define REGISTER_TO_FACTORY(BaseClass, DerivedClass) \
const FactoryRegister<BaseClass, DerivedClass> \
REGISTER_WITH_##BaseClass_##DerivedClass(#DerivedClass)
with codes, the compiler(gcc4.8.2) show below:
factory.h: In constructor 'FactoryRegister<T1, T2>::FactoryRegister(std::string)':
factory.h:62:44: error: expected primary-expression before '>' token
Factory<T1>::get_instance()->add<T2>(name);
Could any body tell the reason ?
Quote from C++'03 Standard 14.2/4:
When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.
Factory<T1>::get_instance()-> template add<T2>(name);
Btw, some compilers has special mode that allows to compile original code without errors
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.