Skip to content

Instantly share code, notes, and snippets.

@pkrusche
Last active July 17, 2022 12:34
Show Gist options
  • Save pkrusche/5501253 to your computer and use it in GitHub Desktop.
Save pkrusche/5501253 to your computer and use it in GitHub Desktop.
A generic factory in C++
#!/bin/bash
CC=g++
${CC} -o if_test main.cpp interface.cpp interface_impl_1.cpp interface_impl_2.cpp
/**
* @file interface.cpp
* @author Peter Krusche
*
*/
#include "interface.h"
#include <map>
#include <string>
typedef std::map<std::string, Pfactory> FMAP;
typedef boost::shared_ptr<FMAP> PFMAP;
struct FactorySingleton {
static FMAP & get() {
static FMAP factory_map;
return factory_map;
}
} fs;
/** make one. */
Pinterface interface::create(const char * name) {
std::string n(name);
FMAP::iterator it = fs.get().find(n);
if (it == fs.get().end()) {
throw "I don't know this type.";
}
return it->second->make_me();
}
/** register a simulator factory with a given name */
void interface::register_me(const char * name, Pfactory fac) {
fs.get()[std::string(name)] = fac;
}
/**
* @file interface.h
* @author Peter Krusche
*
*/
#ifndef INTERFACE_H
#define INTERFACE_H
#include <boost/shared_ptr.hpp>
class interface;
typedef boost::shared_ptr<interface> Pinterface;
/** factory interface */
class factory {
public:
virtual Pinterface make_me() = 0;
};
typedef boost::shared_ptr<factory> Pfactory;
/** generic factory */
template <class _s>
class generic_factory : public factory {
public:
virtual Pinterface make_me() {
Pinterface p(new _s());
return p;
}
};
/** the interface we want to implement elsewhere */
class interface {
public:
virtual ~interface() {}
virtual void do_something() = 0;
/** make one. */
static Pinterface create(const char * name);
/** register a simulator factory with a given name */
static void register_me(const char * name, Pfactory fac);
};
/** registration by name */
template <class _s>
class register_factory {
public:
register_factory(const char * name) {
Pfactory pf (new generic_factory<_s>);
interface::register_me(name, pf);
}
#define REGISTER_INTERFACE(name, type) \
namespace { \
static register_factory<type> fac(name); \
};
};
#endif
/**
* @file interface_impl_1.cpp
* @author Peter Krusche
*
*/
#include "interface.h"
#include <iostream>
class interface_impl_1 : public interface {
public:
interface_impl_1() {}
virtual ~interface_impl_1() {}
virtual void do_something() {
std::cout << "Hi there, I am implementation number 1." << std::endl;
}
};
REGISTER_INTERFACE("impl1", interface_impl_1);
/**
* @file interface_impl_1.cpp
* @author Peter Krusche
*
*/
#include "interface.h"
#include <iostream>
class interface_impl_2 : public interface {
public:
interface_impl_2() {}
virtual ~interface_impl_2() {}
virtual void do_something() {
std::cout << "Hi there, I am implementation number 2. I am very different from number 1." << std::endl;
}
};
REGISTER_INTERFACE("impl2", interface_impl_2);
/**
* @file main.cpp
* @author Peter Krusche
*
*/
#include "interface.h"
#include <iostream>
int main(int argc, char const *argv[]) {
Pinterface if1 = interface::create("impl1");
using namespace std;
cout << "Using impl1 : " << endl;
if1->do_something();
cout << endl;
Pinterface if2 = interface::create("impl2");
cout << "Using impl2 : " << endl;
if2->do_something();
cout << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment