Last active
July 17, 2022 12:34
-
-
Save pkrusche/5501253 to your computer and use it in GitHub Desktop.
A generic factory in C++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
CC=g++ | |
${CC} -o if_test main.cpp interface.cpp interface_impl_1.cpp interface_impl_2.cpp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @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); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @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); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @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