Polymorphism and function binding - c++

For an event system i'm writing i want to bind callbacks to a list of functions.
Here is a basic example of what i want to do:
#include <iostream>
#include <functional>
#include <string>
class Base {
public:
virtual std::string getType() const = 0;
};
class Derived : public Base {
protected:
int some_data;
public:
Derived(int some_data): some_data(some_data) {}
virtual std::string getType() const {
return "Derived";
}
int getData() const {
return this->some_data;
}
};
class DerivedTwo : public Base {
protected:
double some_data;
public:
DerivedTwo(double some_data): some_data(some_data) {}
virtual std::string getType() const {
return "DerivedTwo";
}
// The type of data is not always the same.
double getData() const {
return this->some_data;
}
};
// The type of member should ALWAYS be Derived but then i can't store it in <callback>
void onDerivedEvent(Base& member) {
std::cout << member.getType() << std::endl;
// This is obviously not possible with member being a base class object
// member.getData();
}
// The type of member should ALWAYS be DerivedTwo but then i can't store it in <callback>
void onDerivedTwoEvent(Base& member) {
std::cout << member.getType() << std::endl;
}
int main() {
std::function<void(Base&)> callback;
callback = std::bind(onDerivedEvent, std::placeholders::_1);
callback(Derived(2));
callback = std::bind(onDerivedTwoEvent, std::placeholders::_1);
callback(DerivedTwo(3.0));
return 0;
}
The only thing i would like to change is that onCallback() should take a derived class member as argument instead of a reference to a base object, so i can call getData() for example.
In this example this would mean:
void onCallback(Derived& derived);
However, if i do this, i can no longer bind() the method to callback because the argument types are not matching.
Does anyone know how to make this work?
// EDIT
Sorry for the confusion here, i updated the source code with some more specifics and examples to maybe clarify what im doing here.
Note:
Since it seems like this is very relevant, here is the specific use case for what i'm trying to do here:
It's part of an event system for an engine i'm building. There are basic events pre-defined but it should be extendable with more specific events by a user using this engine. So there is not definitive list of derived classes. Then some object can subscribe to a specific event type and whenever the central event bus recieves such an event, it calls all subscribed callback functions with the event as argument. The reason i am not adding a one and for all handle function in the derived class is, the events an be used in multiple ways.
Answers to some questions from the comments:
What should happen if you pass onCallback an object that isn't that specific Derived&? (ie, add a Derived2 which has a doStuff2. Pass it to callback. What do you want to happen?
That should not be possible.
I might have not calrified that and also had a misleading information at the beginning which i have editted since then. The type of the passed derived class is always known beforehand. For example: onKeyEvent will always recieve a KeyEvent object and not a base class object or any other derived variants.
However, the variable to which this function is bound should be able to store functions which accept different derived classes from Base
This is my storage for all events:
std::map<EventType, std::list<std::function<void(const Event&)>>> listener_map;
Why isn't onCallback a method in Base that Derived overrides
I answered this in a comment. ...The reason i am not adding a one and for all handle function in the derived class is, the events an be used in multiple ways...
Meaning, i might have an KeyEvent which has the data to a key (which key, is it pressed/released/held) and the listening function(s) can use this data for whatever it wants. (Check if some specific key is pressed, chech if any random key is pressed and so on.) Some other events might not have any data at all and just notify a listener that something happened or have multiple sets of data etc.
Is there, or can there be, a finite, bounded at compile time, central list of all of the types that derive from Base at any point in your code?
In theory yes. During compilation there will be a finite number of Derived classes. However these might be different for the compilation of the library and the compilation of the project using this library.

template<class Base>
struct poly_callback {
template<class T>
static poly_callback make( std::function<void(T&)> f ) {
return { std::function<void(void*)>( [f]( void* ptr ) { f(*static_cast<T*>(static_cast<Base*>(ptr))); }) };
}
template<class T>
poly_callback( void(*pf)(T&) ):poly_callback( make<T>( pf ) ) {}
poly_callback( poly_callback const& ) = default;
poly_callback( poly_callback && ) = default;
void operator()( Base& b ) {
return type_erased( static_cast<void*>(std::addressof(b)) );
}
private:
std::function<void(void*)> type_erased;
poly_callback( std::function<void(void*)> t ):type_erased(std::move(t)) {}
};
A poly_callback<Event> can store a callable with signature compatible to void(Derived&), where Derived is derived from Event. It must be called with exactly an instance of the Derived& type or undefined behavior results as it blindly downcasts.
Stop using std::bind, it is functionally obsolete.
class Base {
public:
virtual std::string getType() const = 0;
};
class Derived : public Base {
protected:
int some_data;
public:
Derived(int some_data): some_data(some_data) {}
virtual std::string getType() const {
return "Derived";
}
int getData() const {
return this->some_data;
}
};
class DerivedTwo : public Base {
protected:
double some_data;
public:
DerivedTwo(double some_data): some_data(some_data) {}
virtual std::string getType() const {
return "DerivedTwo";
}
// The type of data is not always the same.
double getData() const {
return this->some_data;
}
};
// The type of member should ALWAYS be Derived but then i can't store it in <callback>
void onDerivedEvent(Derived& member) {
std::cout << member.getType() << "\n";
std::cout << member.getData() << "\n";
}
// The type of member should ALWAYS be DerivedTwo but then i can't store it in <callback>
void onDerivedTwoEvent(DerivedTwo& member) {
std::cout << member.getType() << "\n";
std::cout << member.getData() << "\n";
}
struct callbacks {
std::unordered_map< std::string, std::vector< poly_callback<Base> > > events;
void invoke( std::string const& name, Base& item ) {
auto it = events.find(name);
if (it == events.end())
return;
for (auto&& f : it->second)
f( item );
}
template<class Derived>
void connect( std::string const& name, void(*pf)(Derived&) )
{
events[name].push_back( pf );
}
template<class Derived>
void connect_T( std::string const& name, std::function<void(Derived&)> f )
{
events[name].push_back( std::move(f) );
}
};
int main() {
callbacks cb;
cb.connect("one", onDerivedEvent );
cb.connect("two", onDerivedTwoEvent );
Derived d(7);
DerivedTwo d2(3.14);
cb.invoke( "one", d );
cb.invoke( "two", d2 );
return 0;
}
Live example.
This can be tweaked for safety and usability. For example, check that the typeid actually matches.
Output is:
Derived
7
DerivedTwo
3.14
and as you can see, the callback functions take Derived& and DerivedTwo& objects.
In my experience this is a bad plan.
Instead, have a broadcaster<KeyboardEvent> keyboard; and don't look up your event registry systems with strings.
A map from string-to-callback only makes sense if there is some way to treat the callbacks uniformly. And you don't want to treat these callbacks uniformly. Even if you chose to store them uniformly for efficiency sake (useful in ridiculously huge frameworks), I'd want type-safe APIs not a map.

Related

how to extract template derived class's method into non-template base class

I want using polymorphism in C++, I am try to extract method shows in all derived class into base class.
For example:
I have two class, HouseA and HouseB, they are template class.
And they are derived from base class BaseHouse.
class BaseHouse
{
public:
//other thing
private:
};
template <typename Type>
class HouseA : public BaseHouse
{
public:
HouseA(Type object_input) : object(object_input)
{
}
// other thing about HouseA
Type &getObject()
{
std::cout << "this is House A" << std::endl;
return object;
}
private:
Type object;
};
template <typename Type>
class HouseB : public BaseHouse
{
public:
HouseB(Type object_input) : object(object_input)
{
}
// other thing about HouseB
Type &getObject()
{
std::cout << "this is House B" << std::endl;
return object;
}
private:
Type object;
};
Bacause of polymorphism, we using base class's pointer to access derivated class object. When I need to call method defined in derivated class, I am always transfer base class pointer into derivated class pointer:
int main()
{
HouseA<int> house_a(5);
int x = house_a.getObject();
BaseHouse *base_ptr = &house_a;
// suppose after some complicate calculate calculation
// we only have the base class pointer can access derivated class object
HouseA<int> *ptr_a = (HouseA<int> *)base_ptr; //transfer base class pointer into derivated class pointer
ptr_a->getObject();
return 0;
}
But the derived class HouseA and HouseB both have the method getObject.
So I want to extract template derived class's method into non-template base class.
For some reason, we suppose that the base class BaseHouse can not be template class.
Is there any way I can do that?
Thanks in advance.
If the signature of the derived member depends on the template arguments (as your getObject does on Type) the member cannot be extracted into a non-template base. At least not without removing the ability of the member's signature to vary based on template arguments.
Maybe not exactly a classical Visitor, but...
Okay, the basic idea is we have to somehow capture and encapsulate templated processing into a single entity ready-to-use in a run-time polymorphic construct.
Let's start with a simple class hierarchy:
struct Consumer;
struct Base {
virtual void giveObject(Consumer const &) const = 0;
virtual ~Base() = default;
};
struct Derived1: Base {
Derived1(int x): x(x) {}
void giveObject(Consumer const &c) const override {
c(x);
}
private:
int x;
};
struct Derived2: Base {
Derived2(double y): y(y) {}
void giveObject(Consumer const &c) const override {
c(y);
}
private:
double y;
};
So far, it is very simple: the Base class has a pure virtual method that accepts an object of type Consumer and a concrete implementation of this method is expected to expose to Consumer the relevant part of the internal state of its particular implementor (which is a subtype of Base). In other words, we have taken that 'virtual template' idiom and hid it inside the Consumer. Ok, what could it possibly be?
First option, if you know in advance at compile-time (at source code-time, more exactly) what it could possibly do, i.e. there's only one algorithm of consumption per each object type, and the set of types is fixed, it is quite straightforward:
struct Consumer {
void consume(int x) const { std::cout << x << " is an int.\n"; }
void consume(double y) const { std::cout << y << " is a double.\n"; }
template<typename T> void consume(T t) const {
std::cout << "Default implementation called for an unknown type.\n";
}
};
etc.
More elaborate implementation would allow run-time construction of a templated entity. How is that even possible?
Alexandrescu in his "Modern C++ Design" uses typeid to store particular type handlers in a single data structure. In a brief, this could be something like:
struct Handler {
virtual ~Handler() = default; // now it's an empty polymorphic base
};
template<typename T> struct RealHandler: Handler {
RealHandler(std::function<void(T)> f): f(std::move(f)) {}
void handle(T x) {
f(x);
}
private:
std::function<void(T)> f;
};
#include <map>
#include <type_info>
#include <functional>
struct Consumer {
template<typename T> void consume(T t) const {
auto f{knownHandlers.find(typeid(t))};
if(f != knownHandlers.end()) {
RealHandler<T> const &rh{
dynamic_cast<RealHandler<T> const &>(*f->second)};
rh.handle(t);
}
else {
// default implementation for unregistered types here
}
}
template<typename T> Consumer &register(std::function<void(T)> f) {
knownHandlers[typeid(T)] = std::make_unique<RealHandler<T>>(std::move(f));
}
private:
std::map<std::type_info, std::unique_ptr<Handler>> knownHandlers;
};
Haven't actually tested it, as I don't like typeids and other RTTI much. What I have quickly tested is another solution that requires neither maps nor typeinfo to store handlers in a templated manner. Still it uses a small trick, like how can we possibly pass, keep and retrieve information of an arbitrary type with the same call.
struct Consumer {
Consumer() {}
template<typename T> void consume(T t) const {
auto f{setSlot<T>()};
if(f) f(t);
else {
// default implementation for an unset slot
std::cout << t / 2 << '\n';
}
}
template<typename T>
std::function<void(T)> &setSlot(
std::function<void(T)> f = std::function<void(T)>{}) const
{
static std::function<void(T)> slot;
if(f) { // setter
slot = std::move(f);
}
return slot;
}
};
Here, setSlot() is used to store a handler for a particular type: when called with a non-empty argument, it stores that argument; and then returns its currently kept value. With Consumer so defined, the class hierarchy from above works as:
int main() {
Consumer c;
c.setSlot<int>([](int x){ std::cout << x << " is an int!\n"; });
Base const &b1{Derived1{42}};
Base const &b2{Derived2{3.14}};
b1.giveObject(c);
b2.giveObject(c);
}
Output:
42 is an int!
1.57
In the first line we see a message printed by a custom int handler; in the second line, a default message is printed for the double type, as no custom handler for double was installed.
One obvious drawback of this implementation is that handlers are stored in static variables thus all Consumers share the same handlers for all types, so Consumer here is actually a monostate. At least, you can change implementations for types at run-time, unlike if you had fixed Consumers of the very first approach. The maps-of-typeids approach from above shouldn't have this drawback, in exchange for some performance cost.

Design pattern for method returning different types/classes

This is a question for the Object Design Pattern specialists.
Let's assume I have a Parser class that is in charge of reading/parsing a stream of data (that carry information packets of different types). Each of these packets carry a different type of information, so ideally I would have a class for each type of packet (PacketTypeA, PacketTypeB, ... each one with its own interface).
class Parser {
public:
/* ctor */
/* dtor */
void read_packet(/* arguments */);
// methods...
private:
// more methods...
}
The method Parser::read_packet would then go through the stream and return a class (or pointer or reference to a class) to the appropriate packet type.
Would you use void pointers for this? How about a generic class (PacketBasicInterface) that would provide a common (partial) interface to query about the type of packet (so that any decision could then be made at runtime)?
// Pure virtual (abstract) class to provide a common (and partial) interface
class PacketBasicInterface {
public:
std::string whoAmI() const = 0;
bool amIofType(const std::string& type) const = 0;
}
// Class to access data of type A packet
class PacketTypeA : public PacketBasicInterface {
public:
// methodA_1()
// methodA_2(), ...
}
// Class to access data of type A packet
class PacketTypeB : public PacketBasicInterface {
public:
// methodB_1()
// methodB_2(), ...
}
Any thought or feedback would be very much appreciated!
Many thanks!
This is what std::variant is for.
I would define an enumeration class, that enumerates all possible packet types:
enum class packet_type {initialization_packet, confirmation_type, ... };
And have read_packet return a tuple of packet_type and a variant:
typedef std::variant< ... > packet_info;
std::tuple<packet_type, packet_info> read_packet();
Don't really need a formal enumeration, but it makes it easier to figure out what to do with the variant.
A few variations on this general approach include:
Using an opaque std::string, rather than a fixed enumeration, to specify the packet type.
Using std::any instead of a formal std::variant.
Instead of using a simple enumeration, or an opaque token like a std::string, use a slightly non-trivial class to define the packet type, with the class's methods taking the variant metadata as parameters, and encapsulating the operations that can be done on the packet.
Of course, as noted in the cited link, std::variant requires C++17. Which would be a good argument for you to update your compiler: you get a simple way to implement a completely type-safe approach.
Double dispatching can be the way to go if you are looking for a design pattern from the realm of object oriented programming.
It follows a minimal, working example:
#include<iostream>
struct Visitor;
struct PacketBasicInterface {
virtual void accept(Visitor &) = 0;
};
struct PacketTypeA: PacketBasicInterface {
void accept(Visitor &) override;
};
struct PacketTypeB: PacketBasicInterface {
void accept(Visitor &) override;
};
struct Visitor {
void visit(PacketTypeA) {
std::cout << "PacketTypeA" << std::endl;
}
void visit(PacketTypeB) {
std::cout << "PacketTypeB" << std::endl;
}
};
void PacketTypeA::accept(Visitor &visitor) {
visitor.visit(*this);
}
void PacketTypeB::accept(Visitor &visitor) {
visitor.visit(*this);
}
struct Parser {
PacketBasicInterface * read_packet() {
return new PacketTypeB{};
}
};
int main() {
Visitor visitor;
auto *packet = Parser{}.read_packet();
packet->accept(visitor);
delete packet;
}
Would you use void pointers for this?
No.
How about a generic class (PacketBasicInterface) that would provide a common (partial) interface to query about the type of packet (so that any decision could then be made at runtime)?
That makes most sense to me.
Let me refine that. Yes, it will be good to have a generic base class. However, when parsing the stream to construct sub-types of the base class, don't rely on an if-else type approach. Rather, use a factory pattern. Let the various factories construct the right object types based an on a key, which I assume will be available from the data being parsed.
If you encounter the string "PacketTypeA" in your data, you would expect that PacketTypeAFactory will be responsible for constructing the object.
FWIW, this approach is scalable for lots of sub-types of the base class. We use this approach at my work and it has served us well for over twenty years.
Here's the skeletal structure of the code base I am thinking of:
The classes.
class PacketBasicInterface { };
class PacketTypeA : public PacketBasicInterface { };
class PacketTypeB : public PacketBasicInterface { };
The interface of the factory.
// PacketFactory.h
class PacketFactory
{
public:
static PacketBasicInterface* makePacket(std::string const& packetData);
static void registerFactory(std::string const& key, PacketFactory* factory);
virtual PacketBasicInterface* make(std::string const& packetData) = 0;
virtual ~PacketFactory() {}
};
Implementation of the framework that makes the factory work.
// PacketFactory.cpp
#include "PacketFactory.h"
namespace PacketBasicInterface_Impl
{
using PacketFactoryMap = std::map<std::string, PacketFactory*>;
PacketFactoryMap& getPacketFactoryMap()
{
static PacketFactoryMap theMap;
return theMap;
}
};
uisng namespace PacketBasicInterface_Impl;
PacketBasicInterface* PacketFactory::makePacket(std::string const& packetData)
{
std::string key = extractKey(packetData);
PacketFactoryMap& theMap = getPacketFactoryMap();
PacketFactoryMap::iterator iter = theMap.find(key);
if ( iter == theMap.end() )
{
return nullptr;
}
return iter->second->make(packetData);
}
void registerFactory(std::string const& key, PacketFactory* factory)
{
getPacketFactoryMap()[key] = factory;
}
Code for making objects of type PacketTypeA using the factory pattern.
// PacketTypeAFactory.cpp
#include "PacketFactory.h"
#include "PacketTypeA.h"
class PacketTypeAFactory : public PacketFactory
{
public:
virtual PacketBasicInterface* make(std::string const& packetData)
{
PacketTypeA* packet = new PacketTypeA();
// Flesh out packet with data pulled from packetData
// ...
//
return packet;
}
struct Initializer
{
Initializer() { PacketFactory::registerFactory("PacketTypeA", new PacketTypeAFactory); }
};
};
// Constructing this object at static initialization time makes sure
// that PacketTypeAFactory is registered with PacketFactory when the
// stream data need to be parsed.
static PacketTypeAFactory::Initializer initializer;
The code for making objects of type PacketTypeB is very similar to the
code for making objects of type PacketTypeA using the factory pattern.
// PacketTypeBFactory.cpp
#include "PacketFactory.h"
#include "PacketTypeB.h"
class PacketTypeBFactory : public PacketFactory
{
public:
virtual PacketBasicInterface* make(std::string const& packetData)
{
PacketTypeA* packet = new PacketTypeA();
// Flesh out packet with data pulled from packetData
// ...
//
return packet;
}
struct Initializer
{
Initializer() { PacketFactory::registerFactory("PacketTypeB", new PacketTypeBFactory); }
};
};
// Constructing this object at static initialization time makes sure
// that PacketTypeBFactory is registered with PacketFactory when the
// stream data need to be parsed.
static PacketTypeBFactory::Initializer initializer;
Client code.
std::string packetData;
while ( getPacketData(packetData) )
{
PacketBasicInterface* packet = PacketFactory::makePacket(packetData);
if ( packet == nullptr )
{
// Deal with error.
}
else
{
// Use packet
}
}

Overwrite Base Class Member with New Type

I'm trying to use C++ to emulate something like dynamic typing. I'm approaching the problem with inherited classes. For example, a function could be defined as
BaseClass* myFunction(int what) {
if (what == 1) {
return new DerivedClass1();
} else if (what == 2) {
return new DerivedClass2();
}
}
The base class and each derived class would have the same members, but of different types. For example, BaseClass may have int xyz = 0 (denoting nothing), DerivedClass1 might have double xyz = 123.456, and DerivedClass2 might have bool xyz = true. Then, I could create functions that returned one type but in reality returned several different types. The problem is, when ere I try to do this, I always access the base class's version of xyz. I've tried using pointers (void* for the base, and "correct" ones for the derived classes), but then every time I want to access the member, I have to do something like *(double*)(obj->xyz) which ends up being very messy and unreadable.
Here's an outline of my code:
#include <iostream>
using std::cout;
using std::endl;
class Foo {
public:
Foo() {};
void* member;
};
class Bar : public Foo {
public:
Bar() {
member = new double(123.456); // Make member a double
};
};
int main(int argc, char* args[]) {
Foo* obj = new Bar;
cout << *(double*)(obj->member);
return 0;
};
I guess what I'm trying to ask is, is this "good" coding practice? If not, is there a different approach to functions that return multiple types or accept multiple types?
That is not actually the way to do it.
There are two typical ways to implement something akin to dynamic typing in C++:
the Object-Oriented way: a class hierarchy and the Visitor pattern
the Functional-Programming way: a tagged union
The latter is rather simple using boost::variant, the former is well documented on the web. I would personally recommend boost::variant to start with.
If you want to go down the full dynamic typing road, then things get trickier. In dynamic typing, an object is generally represented as a dictionary containing both other objects and functions, and a function takes a list/dictionary of objects and returns a list/dictionary of objects. Modelling it in C++ is feasible, but it'll be wordy...
How is an object represented in a dynamically typed language ?
The more generic representation is for the language to represent an object as both a set of values (usually named) and a set of methods (named as well). A simplified representation looks like:
struct Object {
using ObjectPtr = std::shared_ptr<Object>;
using ObjectList = std::vector<ObjectPtr>;
using Method = std::function<ObjectList(ObjectList const&)>;
std::map<std::string, ObjectPtr> values;
std::map<std::string, Method> methods;
};
If we take Python as an example, we realize we are missing a couple things:
We cannot implement getattr for example, because ObjectPtr is a different type from Method
This is a recursive implementation, but without the basis: we are lacking innate types (typically Bool, Integer, String, ...)
Dealing with the first issue is relatively easy, we transform our object to be able to become callable:
class Object {
public:
using ObjectPtr = std::shared_ptr<Object>;
using ObjectList = std::vector<ObjectPtr>;
using Method = std::function<ObjectList(ObjectList const&)>;
virtual ~Object() {}
//
// Attributes
//
virtual bool hasattr(std::string const& name) {
throw std::runtime_error("hasattr not implemented");
}
virtual ObjectPtr getattr(std::string const&) {
throw std::runtime_error("gettattr not implemented");
}
virtual void setattr(std::string const&, ObjectPtr) {
throw std::runtime_error("settattr not implemented");
}
//
// Callable
//
virtual ObjectList call(ObjectList const&) {
throw std::runtime_error("call not implemented");
}
virtual void setcall(Method) {
throw std::runtime_error("setcall not implemented");
}
}; // class Object
class GenericObject: public Object {
public:
//
// Attributes
//
virtual bool hasattr(std::string const& name) override {
return values.count(name) > 0;
}
virtual ObjectPtr getattr(std::string const& name) override {
auto const it = values.find(name);
if (it == values.end) {
throw std::runtime_error("Unknown attribute");
}
return it->second;
}
virtual void setattr(std::string const& name, ObjectPtr object) override {
values[name] = std::move(object);
}
//
// Callable
//
virtual ObjectList call(ObjectList const& arguments) override {
if (not method) { throw std::runtime_error("call not implemented"); }
return method(arguments);
}
virtual void setcall(Method m) {
method = std::move(m);
}
private:
std::map<std::string, ObjectPtr> values;
Method method;
}; // class GenericObject
And dealing with the second issue requires seeding the recursion:
class BoolObject final: public Object {
public:
static BoolObject const True = BoolObject{true};
static BoolObject const False = BoolObject{false};
bool value;
}; // class BoolObject
class IntegerObject final: public Object {
public:
int value;
}; // class IntegerObject
class StringObject final: public Object {
public:
std::string value;
}; // class StringObject
And now you need to add capabilities, such as value comparison.
You can try the following design:
#include <iostream>
using std::cout;
using std::endl;
template<typename T>
class Foo {
public:
Foo() {};
virtual T& member() = 0;
};
class Bar : public Foo<double> {
public:
Bar() : member_(123.456) {
};
virtual double& member() { return member_; }
private:
double member_;
};
int main(int argc, char* args[]) {
Foo<double>* obj = new Bar;
cout << obj->member();
return 0;
};
But as a consequence the Foo class already needs to be specialized and isn't a container for any type anymore.
Other ways to do so, are e.g. using a boost::any in the base class
If you need a dynamic solution you should stick to using void* and size or boost::any. Also you need to pass around some type information as integer code or string so that you can decode the actual type of the content.
See also property design pattern.
For example, you can have a look at zeromq socket options https://github.com/zeromq/libzmq/blob/master/src/options.cpp

minimal reflection in C++

I want to create a class factory and I would like to use reflection for that. I just need to
create a object with given string and invoke only few known methods.
How i can do that?
You will have to roll your own. Usually you have a map of strings to object creation functions.
You will need something like the follwing:
class thing {...};
/*
class thing_A : public thing {...};
class thing_B : public thing {...};
class thing_C : public thing {...};
*/
std::shared_ptr<thing> create_thing_A();
std::shared_ptr<thing> create_thing_C();
std::shared_ptr<thing> create_thing_D();
namespace {
typedef std::shared_ptr<thing> (*create_func)();
typedef std::map<std::string,create_func> creation_map;
typedef creation_map::value_type creation_map_entry;
const creation_map_entry creation_map_entries[] = { {"A", create_thing_A}
, {"B", create_thing_B}
, {"C", create_thing_C} };
const creation_map creation_funcs(
creation_map_entries,
creation_map_entries + sizeof(creation_map_entries)
/ sizeof(creation_map_entries[0] );
}
std::shared_ptr<thing> create_thing(const std::string& type)
{
const creation_ma::const_iterator it = creation_map.find(type);
if( it == creation_map.end() ) {
throw "Dooh!"; // or return NULL or whatever suits you
}
return it->second();
}
There are other ways to do this (like having a map of strings to objects from which to clone), but I think they all boil down to having a map of strings to something related to the specific types.
There is no reflection in C++, directly supported by the standard.
However C++ is sufficiently low-level that you can implement some minimal support for reflection to complete the task at hand.
For the simple task of creating a Factory, you usually use the Prototype approach:
class Base
{
public:
virtual Base* clone() const = 0;
virtual ~Base();
};
class Factory
{
public:
std::unique_ptr<Base> get(std::string const& name);
void set(std::string const& name, std::unique_ptr<Base> b);
private:
boost::ptr_map<std::string,Base> mExemplars;
};
Of course, those "known methods" that you are speaking about should be defined within the Base class, which acts as an interface.
There is no reflection in C++, so you should restate your question trying to explain what are the requirements that you would have fulfilled with the reflection part of it.
Depending on your actual constraints and requirements, there are a few things that you can do. The first approach that I would take would be creating an abstract factory where concrete factories can register and provide a simple interface:
class Base {}; // shared base by all created objects
class ConcreteFactoryBase {
public:
virtual ~ConcreteFactoryBase() {}
virtual Base* create() const = 0; // actual construction
virtual std::string id() const = 0; // id of the types returned
};
class AbstractFactory
{
typedef std::map<std::string, ConcreteFactory* > factory_map_t;
public:
void registerFactory( ConcreteFactoryBase* factory ) {
factories[ factory->id() ] = factory;
}
Base* create( std::string const & id ) const {
factory_map_t::const_iterator it = factories.find( id );
if ( it == factories.end() ) {
return 0; // or throw, or whatever makes sense in your case
}
return (*it)->create();
}
~AbstractFactory(); // ensure that the concrete factories are deleted
private:
std::map<ConcreteFactoryBase*> factories;
};
The actual concrete factories can be implemented manually but they can probably be templated, unless the constructors for the different types require different arguments:
template <typename T>
class ConcreteFactory : public ConcreteFactoryBase {
public:
ConcreteFactory( std::string const & id ) : myid(id) {}
virtual Base* create() const {
return new T;
}
virtual std::string id() const {
return myid;
}
private:
std::string myid;
};
class Test : public Base {};
int main() {
AbstracFactory factory;
factory.register_factory( new ConcreteFactory<Test>("Test") );
}
Optionally you could adapt the signatures so that you can pass arguments to the constructor through the different layers.
Then again, by knowing the actual constraints some other approaches might be better. The clone() approach suggested elsewhere is good (either by actually cloning or by creating an empty object of the same type). That is basically blending the factory with the objects themselves so that each object is a factory of objects of the same type. I don't quite like mixing those two responsabilities but it might be one of the simplest approaches with less code to write.
You could use typeid & templates to implement the factory so you won't need strings at all.
#include <string>
#include <map>
#include <typeinfo>
//***** Base *****
class Base
{
public:
virtual ~Base(){} //needs to be virtual to make typeid work
};
//***** C1 *****
class C1 : public Base
{};
//***** Factory *****
class Factory
{
public:
template <class T>
Base& get();
private:
typedef std::map<std::string, Base> BaseMap;
BaseMap m_Instances;
};
template <class T>
Base& Factory::get()
{
BaseMap::const_iterator i = m_Instances.find(typeid(T).name());
if(i == m_Instances.end()) {
m_Instances[typeid(T).name()] = T();
}
return m_Instances[typeid(T).name()];
}
//***** main *****
int main(int argc, char *argv[])
{
Factory f;
Base& c1 = f.get<C1>();
return 0;
}

Technique for Using Templates and Virtual Functions

A while back I learned about the Curiously Recurring Template Pattern (http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern), and it reminded me of a technique I had used to implement an event queue cache.
The basic idea is that we take advantage of a Base class pointer to store a container of homogeneous pointer types. However because the Derived class is a template class, which stores an item of type T, what we are really storing is a list of heterogeneous types.
I was curious if anyone has seen this technique, which is perhaps interesting, and if so if anyone has named it? Anyone care to critique it? Is there a better way to achieve my end here?
Thanks.
#include <iostream>
#include <algorithm>
#include <functional>
#include <list>
#include <string>
class Base
{
public:
Base(){}
virtual ~Base(){}
virtual void operator()() = 0;
};
template<typename C, typename T>
class Derived : public Base
{
public:
Derived(C* c, T item) : consumer_(c), item_(item) {}
virtual void operator()()
{
consumer_->consume(item_);
}
C* consumer_;
T item_;
};
class Consumer
{
bool postpone_;
std::list<Base*> cache_;
public:
Consumer() : postpone_(true)
{
}
void pause()
{
postpone_ = true;
}
void resume()
{
postpone_ = false;
const std::list<Base*>::iterator end = cache_.end();
for ( std::list<Base*>::iterator iter = cache_.begin();
iter != end;
++iter )
{
Base* bPtr = *iter;
bPtr->operator()();
delete bPtr;
}
cache_.clear();
}
void consume(int i)
{
if ( postpone_ )
{
std::cerr << "Postpone int.\n";
cache_.push_back(new Derived<Consumer, int>(this, i));
}
else
{
std::cerr << "Got int.\n";
}
}
void consume(double d)
{
if ( postpone_ )
{
std::cerr << "Postpone double.\n";
cache_.push_back(new Derived<Consumer, double>(this, d));
}
else
{
std::cerr << "Got double.\n";
}
}
void consume(char c)
{
if ( postpone_ )
{
std::cerr << "Postpone char.\n";
cache_.push_back(new Derived<Consumer, char>(this, c));
}
else
{
std::cerr << "Got char.\n";
}
}
};
static Consumer consumer;
void destroy(Base* object)
{
delete object;
}
int main()
{
// Consumer is registered with something that sends events out to lots
// of different consumer types (think observer pattern). Also in the non-toy
// version consumer isn't being passed PODs, but various Event types.
consumer.consume(0);
consumer.consume(0.1f);
consumer.consume('x');
consumer.resume();
}
The output is:
Postpone int.
Postpone double.
Postpone char.
Got int.
Got double.
Got char.
What you are using is plain polymorphism, as Stephen points out in his comment. While you store different objects internally in the container, you are limited to using the interface defined in Base. That is, of course, unless you intend to add type checking and downcasts to actually retrieve the values. There is just a limited amount of things that you can do with unrelated objects.
Depending on what you are actually wanting to achieve you might consider using other solutions like boost::any/boost::variant if what you want is to actually store unrelated types (in the few cases where this makes sense --cells in a spreadsheet, for example).
anyone has named it?
I think it is an adapter pattern implemented without using inheritance from T.
Anyone care to critique it?
YOu could have used short template function instead of this class. Or you could use template function that returns template class. Template function can automatically guess required types - sou you could omit <> and do less typing.
Nice.
You're utilizing compiler's power to generate templated series of derived classes and it's actually cool that you can mix plain derived classes
(written by yourself) with template-specialized derived classes and with compiler-generated ones
(built as result of template instantiation).
class Base { ... };
template <typename Y> class Derived1 : public Base { ... };
template <specialization>
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
This could be useful, but it doesn't somehow extend the polymorphism term, because you're still limited to the Base class interface.
Also, you could write a plain factory which would have some templated method for generating subclasses and use it to avoid writing new Derived1<std::string>..., but write something like
std::string a;
Base* base = Factory.Create(a)