I want to define structs to hold various application parameters:
struct Params
{
String fooName;
int barCount;
bool widgetFlags;
// ... many more
};
but I want to be able to enumerate, get and set these fields by name, eg so that I can expose them to automation APIs and for ease in serialisation:
Params p;
cout << p.getField("barCount");
p.setField("fooName", "Roger");
for (String fieldname : p.getFieldNames()) {
cout << fieldname << "=" << p.getField(fieldName);
}
Is there a good way of defining a binding from a string label to a get/set function? Along the lines of this (very much pseudocode):
Params() {
addBinding("barCount", setter(&Params::barCount), getter(&Params::barCount));
...
I know that other options are to auto-generate the struct from an external metadata file, and another is to store the struct as a table of (key,value) pairs, but I would rather keep the data in a struct.
I do have a Variant type which all fields are convertible to.
C++ doesn't have reflection so this isn't something you can do cleanly. Also, by referring to members as strings, you have to try to side-step the strongly typed nature of the language. Using a serialization library like Boost Serializer or Google Protobuf might be more useful.
That said, if we allow some horribleness, one could do something with an XMacro. (Disclaimer: I wouldn't recommend actually doing this). First you put all the information you need into a macro
#define FIELD_PARAMS \
FIELD_INFO(std::string, Name, "Name") \
FIELD_INFO(int, Count, "Count")
Or alternatively into a header file
<defs.h>
FIELD_INFO(std::string, Name, "Name") \
FIELD_INFO(int, Count, "Count")
Then you'll define FIELD_INFO inside your class to either mean the member declaration, or adding them to a map
struct Params{
Params() {
#define FIELD_INFO(TYPE,NAME,STRNAME) names_to_members.insert(std::make_pair(STRNAME,&NAME));
FIELD_PARAMS
#undef FIELD_INFO
}
template <typename T>
T& get(std::string field){
return *(T*)names_to_members[field];
}
std::map<std::string, void*> names_to_members;
#define FIELD_INFO(TYPE,NAME,STRNAME) TYPE NAME;
FIELD_PARAMS
#undef FIELD_INFO
};
And then you could use it like this
int main (int argc, char** argv){
Params myParams;
myParams.get<std::string>("Name") = "Mike";
myParams.get<int>("Count") = 38;
std::cout << myParams.get<std::string>("Name"); // or myParams.Name
std::cout << std::endl;
std::cout << myParams.get<int>("Count"); // or myParams.Count
return 0;
}
Unfortunately you still need to tell the compiler what the type is. If you have a good variant class and libraries that play well with it, you may be able to get around this.
I'm using a slightly different storage for this: here. The tags I use are ints for some reason, but you could use std::string keys just as well.
There is no really good way (with "good" being a very subjective aspect anyway), because whatever technique you choose is not part of the C++ language itself, but if your goal is serialisation, have a look at Boost Serialization.
I've managed to come up with something that satisfies my particular need. Ari's answer was closest in terms of mapping strings to references to member variables, though it relied on casting from void*. I've got something that's a bit more type-safe:
There's an interface for an individual PropertyAccessor that has a templated class derived from it which binds to a reference to a specific member variable and converts to and from the Variant representation:
class IPropertyAccessor
{
public:
virtual ~IPropertyAccessor() {}
virtual Variant getValueAsVariant() const =0;
virtual void setValueAsVariant(const Variant& variant) =0;
};
typedef std::shared_ptr<IPropertyAccessor> IPropertyAccessorPtr;
template <class T>
class PropertyAccessor : public IPropertyAccessor
{
public:
PropertyAccessor(T& valueRef_) : valueRef(valueRef_) {}
virtual Variant getValueAsVariant() const {return VariantConverter<T>().toVariant(valueRef); }
virtual void setValueAsVariant(const Variant& variant) {return VariantConverter<T>().toValue(variant); }
T& valueRef;
};
// Helper class to create a propertyaccessor templated on a type
template <class T>
static IPropertyAccessorPtr createAccessor(T& valueRef_)
{
return std::make_shared<PropertyAccessor<T>>(valueRef_);
}
The class exposing a collection can now define an ID -> PropertyAccessor and bind its values by reference:
#define REGISTER_PROPERTY(field) accessorMap.insert(AccessorMap::value_type(#field, createAccessor(field)))
class TestPropertyCollection
{
public:
typedef std::map<PropertyID, IPropertyAccessorPtr> AccessorMap;
TestPropertyCollection()
{
REGISTER_PROPERTY(stringField1);
// expands to
// accessorMap.insert(AccessorMap::value_type("stringField", createAccessor(stringField)));
REGISTER_PROPERTY(stringField2);
REGISTER_PROPERTY(intField1);
}
bool getPropertyVariant(const PropertyID& propertyID, Variant& retVal)
{
auto it = accessorMap.find(propertyID);
if (it != accessorMap.end()) {
auto& accessor = it->second;
retVal = accessor->getValueAsVariant();
return true;
}
return false;
}
String stringField1;
String stringField2;
int intField1;
AccessorMap accessorMap
};
Related
Having returned relatively recently to C++ after decades of Java, I am currently struggling with a template-based approach to data conversion for instances where type erasure has been applied. Please bear with me, my nomenclature may still be off for C++-natives.
This is what I am trying to achieve:
Implement dynamic variables which are able to hold essentially any value type
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to hold variable instances in containers, independent of their value type
Convert between variable value and representation using conversion functions
Be able to introduce new representations just by providing new conversion functions
Constraints: use only C++-11 features if possible, no use of libraries like boost::any etc.
A rough sketch of this might look like this:
#include <iostream>
#include <vector>
void convert(const std::string &f, std::string &t) { t = f; }
void convert(const int &f, std::string &t) { t = std::to_string(f); }
void convert(const std::string &f, int &t) { t = std::stoi(f); }
void convert(const int &f, int &t) { t = f; }
struct Variable {
virtual void get(int &i) = 0;
virtual void get(std::string &s) = 0;
};
template <typename T> struct VariableImpl : Variable {
T value;
VariableImpl(const T &v) : value{v} {};
void get(int &i) { convert(value, i); };
void get(std::string &s) { convert(value, s); };
};
int main() {
VariableImpl<int> v1{42};
VariableImpl<std::string> v2{"1234"};
std::vector<Variable *> vars{&v1, &v2};
for (auto &v : vars) {
int i;
v->get(i);
std::string s;
v->get(s);
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
return 0;
}
The code does what it is supposed to do, but obvoiusly I would like to get rid of Variable::get(int/std::string/...) and instead template them, because otherwise every new representation requires a definition and an implementation with the latter being exactly the same as all the others.
I've played with various approaches so far, like virtual templated, methods, applying the CRDT with intermediate type, various forms of wrappers, yet in all of them I get bitten by the erased value type of VariableImpl. On one hand, I think there might not be a solution, because after type erasure, the compiler cannot possibly know what templated getters and converter calls it must generate. On the other hand I think i might be missing something really essential here and there should be a solution despite the constraints mentioned above.
This is a classical double dispatch problem. The usual solution to this problem is to have some kind of dispatcher class with multiple implementations of the function you want to dispatch (get in your case). This is called the visitor pattern. The well-known drawback of it is the dependency cycle it creates (each class in the hierarchy depends on all other classes in the hierarchy). Thus there's a need to revisit it each time a new type is added. No amount of template wizardry eliminates it.
You don't have a specialised Visitor class, your Variable serves as a Visitor of itself, but this is a minor detail.
Since you don't like this solution, there is another one. It uses a registry of functions populated at run time and keyed on type identification of their arguments. This is sometimes called "Acyclic Visitor".
Here's a half-baked C++11-friendly implementation for your case.
#include <map>
#include <vector>
#include <typeinfo>
#include <typeindex>
#include <utility>
#include <functional>
#include <string>
#include <stdexcept>
struct Variable
{
virtual void convertValue(Variable& to) const = 0;
virtual ~Variable() {};
virtual std::type_index getTypeIdx() const = 0;
template <typename K> K get() const;
static std::map<std::pair<std::type_index, std::type_index>,
std::function<void(const Variable&, Variable&)>>
conversionMap;
template <typename T, typename K>
static void registerConversion(K (*fn)(const T&));
};
template <typename T>
struct VariableImpl : Variable
{
T value;
VariableImpl(const T &v) : value{v} {};
VariableImpl() : value{} {}; // this is needed for a declaration of
// `VariableImpl<K> below
// It can be avoided but it is
// a story for another day
void convertValue(Variable& to) const override
{
auto typeIdxFrom = getTypeIdx();
auto typeIdxTo = to.getTypeIdx();
if (typeIdxFrom == typeIdxTo) // no conversion needed
{
dynamic_cast<VariableImpl<T>&>(to).value = value;
}
else
{
auto fcnIter = conversionMap.find({getTypeIdx(), to.getTypeIdx()});
if (fcnIter != conversionMap.end())
{
fcnIter->second(*this, to);
}
else
throw std::logic_error("no conversion");
}
}
std::type_index getTypeIdx() const override
{
return std::type_index(typeid(T));
}
};
template <typename K> K Variable::get() const
{
VariableImpl<K> vk;
convertValue(vk);
return vk.value;
}
template <typename T, typename K>
void Variable::registerConversion(K (*fn)(const T&))
{
// add a mutex if you ever spread this over multiple threads
conversionMap[{std::type_index(typeid(T)), std::type_index(typeid(K))}] =
[fn](const Variable& from, Variable& to) {
dynamic_cast<VariableImpl<K>&>(to).value =
fn(dynamic_cast<const VariableImpl<T>&>(from).value);
};
}
Now of course you need to call registerConversion e.g. at the beginning of main and pass it each conversion function.
Variable::registerConversion(int_to_string);
Variable::registerConversion(string_to_int);
This is not ideal, but hardly anything is ever ideal.
Having said all that, I would recommend you revisit your design. Do you really need all these conversions? Why not pick one representation and stick with it?
Implement dynamic variables which are able to hold essentially any value type
Be able to hold variable instances in containers, independent of their value type
These two requirements are quite challenging on its own. The class templates don't really encourage inheritance, and you already did the right thing to hold what you asked for: introduced a common base class for the class template, which you can later refer to in order to store pointers of the said type in a collection.
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to introduce new representations just by providing new conversion functions
This is where it breaks. Function templates assume common implementation for different types, while inheritance assumes different implementation for the same types.
You goal is to introduce different implementation for different types, and in order to make your requirements viable you have to switch to one of those two options instead (or put up with a number of functions for each case which you have already introduced yourself)
Edit:
One of the strategies you may employ to enforce inheritance approach is generalisation of the arguments to the extent where they can be used interchangeably by the abstract interface. E.g. you may wrap the converting arguments inside of a union like this:
struct Variable {
struct converter_type {
enum { INT, STRING } type;
union {
int* m_int;
std::string* m_string;
};
};
virtual void get(converter_type& var) = 0;
virtual ~Variable() = default;
};
And then take whatever part of it inside of the implementation:
void get(converter_type& var) override {
switch (var.type) {
case converter_type::INT:
convert(value, var.m_int);
break;
case converter_type::STRING:
convert(value, var.m_string);
break;
}
}
To be honest I don't think this is a less verbose approach compared to just having a number of functions for each type combination, but i think you got the idea that you can just wrap your arguments somehow to cement the abstract class interface.
Implement std::any. It is similar to boost::any.
Create a conversion dispatcher based off typeids. Store your any alongside the conversion dispatcher.
"new conversion functions" have to be passed to the dispatcher.
When asked to convert to a type, pass that typeid to the dispatcher.
So we start with these 3 types:
using any = std::any; // implement this
using converter = std::function<any(any const&)>;
using convert_table = std::map<std::type_index, converter>;
using convert_lookup = convert_table(*)();
template<class T>
convert_table& lookup_convert_table() {
static convert_table t;
return t;
}
struct converter_any: any {
template<class T,
typename std::enable_if<
!std::is_same<typename std::decay<T>::type, converter_any>::value, bool
>::type = true
>
converter_any( T&& t ):
any(std::forward<T>(t)),
table(&lookup_convert_table<typename std::decay<T>::type>())
{}
converter_any(converter_any const&)=default;
converter_any(converter_any &&)=default;
converter_any& operator=(converter_any const&)=default;
converter_any& operator=(converter_any&&)=default;
~converter_any()=default;
converter_any()=default;
convert_table const* table = nullptr;
template<class U>
U convert_to() const {
if (!table)
throw 1; // make a better exception than int
auto it = table->find(typeid(U));
if (it == table->end())
throw 2; // make a better exception than int
any const& self = *this;
return any_cast<U>((it->second)(self));
}
};
template<class Dest, class Src>
bool add_converter_to_table( Dest(*f)(Src const&) ) {
lookup_convert_table<Src>()[typeid(Dest)] = [f](any const& s)->any {
Src src = std::any_cast<Src>(s);
auto r = f(src);
return r;
};
return true;
}
now your code looks like:
const bool bStringRegistered =
add_converter_to_table(+[](std::string const& f)->std::string{ return f; })
&& add_converter_to_table(+[](std::string const& f)->int{ return std::stoi(f); });
const bool bIntRegistered =
add_converter_to_table(+[](int const& i)->int{ return i; })
&& add_converter_to_table(+[](int const& i)->std::string{ return std::to_string(i); });
int main() {
converter_any v1{42};
converter_any v2{std::string("1234")};
std::vector<converter_any> vars{v1, v2}; // copies!
for (auto &v : vars) {
int i = v.convert_to<int>();
std::string s = v.convert_to<std::string>();
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
}
live example.
...
Ok, what did I do?
I used any to be a smart void* that can store anything. Rewriting this is a bad idea, use someone else's implementation.
Then, I augmented it with a manually written virtual function table. Which table I add is determined by the constructor of my converter_any; here, I know the type stored, so I can store the right table.
Typically when using this technique, I'd know what functions are in there. For your implementation we do not; so the table is a map from the type id of the destination, to a conversion function.
The conversion function takes anys and returns anys -- again, don't repeat this work. And now it has a fixed signature.
To add support for a type, you independently register conversion functions. Here, my conversion function registration helper deduces the from type (to determine which table to register it in) and the destination type (to determine which entry in the table), and then automatically writes the any boxing/unboxing code for you.
...
At a higher level, what I'm doing is writing my own type erasure and object model. C++ has enough power that you can write your own object models, and when you want features that the default object model doesn't solve, well, roll a new object model.
Second, I'm using value types. A Java programmer isn't used to value types having polymorphic behavior, but much of C++ works much better if you write your code using value types.
So my converter_any is a polymorphic value type. You can store copies of them in vectors etc, and it just works.
I need a way to instantiate objects based on its class name passed by as a std::string. This is working right now, but need to be generalized:
void* create(std::string name) {
if(name == "classOne") return new ClassOne();
else if(name == "classTwo") return new ClassTwo();
/* ... */
}
What i do not have:
Control over the classes to be instantiated: could be thirty party classes. No changes may be done to this classes (i.e. base ancestor, polymorphic creator method, etc...)
Full class name listing: more classes could be added later and should not incur in changes to this factory.
Wrappers around the classes to be instantiated: As a result of the previous two points.
Anything else is a go.
The best use case scenario will be:
int main() {
void *obj = create("classTree"); // create object based on the string name
/* ... */
// once we know by context which specific class we are dealing with
ClassTree *ct = (ClassTree*)obj; // cast to appropiate class
std::cout << ct->getSomeText() << std::endl; // use object
}
As a side, and maybe irrelevant note, take in account the object to be instantiated may come from a class or a struct.
ADDED INFORMATION
I see more context is needed. Here is my particular use case, simplified:
// registration mechanism
int main() {
std::map< std::string, void(*func)(std::string, void*) > processors; // map of processors by class name
processors["ClassFour"] = (void(*)(std::string, void*)) &classFourMessageProcessor; // register processor (cast needed from specific to generic)
}
// function receiving string messages
void externalMessageHandler(std::string msg) {
std::string objType = extractTypeFromMessageHeader(msg); // extract type from message
// now that we know what we are dealing with, create the specific object
void *obj = create(objType); // << creator needed
processors[objType](msg, obj); // dispatch message to process
}
// previously registered message processor
void classFourMessageProcessor(std::String msg, ClassFour *obj) {
std::string streetAddress = msg.substr(10, 15); // knowing the kind of message we can extract information
obj->moveTheEtherTo(streetAddress); // use the created object
}
ADDED INFORMATION
I am using C++11 with the latest GNU compiler.
You can just store a factory function for every class type. An easy way is to use a template
template <typename T>
void* creator() {
return new T();
}
and store those in the map as well (i.e. "ClassFour" links to creator<ClassFour> and to ClassFourMessageProcessor).
Edit: for clarification, processors becomes a
typedef void* (*CreatorFunc)();
typedef void (*ProcessorFunc)(std::string, void*);
typedef std::pair<CreatorFunc, ProcessorFunc> Entry;
std::map< std::string, Entry > processors;
Adding a new class is as simple as
processors["SomeClass"] = Entry(creator<SomeClass>, ClassFourMessageProcessor);
Here's one take:
For each class, create a createInsrance() function (not a method) that instantiate an instance and return a pointer cast to void*. Note this function is not part of the class - just a plain function.
Maintain a map of string to function pointer to createInstance type function.
"Register" each of the relevant classes in the map - add the string-function pointer pair to the map.
Now the generic create will search for the string in the map and invoke the specific createInstane, returning the new instance's ptr.
Now you made no changes to the classes, and can add more classes without reprogramming the factory.
You may probably put at least #1 as a template - be sure to make the compiler instantiate the specific implementation.
maybe the following aproach with a lookup table will be a nice solution.
(Note: I don't know wich compiler are you using, so this solution is for c++03, you could take unordered_map instead map if you are using a compiler with c++11 support)
(Note 2: You could use smart pointers too, and take care of the returns values, whit this example I only wants to show an aproach)
#include <iostream>
#include <string>
#include <map>
#include <vector>
struct ClassMaker
{
virtual void* getInstance() const = 0;
virtual ~ClassMaker() {}
};
class Factory
{
private:
std::map<std::string, ClassMaker*> lookupTable;
typedef typename std::map<std::string, ClassMaker*>::iterator Iterator;
public:
void addClass(const std::string& key, ClassMaker* const newClassMaker)
{
lookupTable[key] = newClassMaker;
}
void* create(const std::string& key)
{
void* result = NULL;
Iterator it = lookupTable.find(key);
if(it != lookupTable.end())
result = (it->second)->getInstance();
return result;
}
void releaseTable()
{
for (Iterator it = lookupTable.begin(); it != lookupTable.end(); ++it)
delete it->second;
}
};
struct IntCreator : public ClassMaker
{
void* getInstance() const
{
return new int;
}
};
struct StringCreator : public ClassMaker
{
void* getInstance() const
{
return new std::string;
}
};
int main()
{
Factory myFactory;
myFactory.addClass("int", new IntCreator);
myFactory.addClass("string", new StringCreator);
int* myInt = reinterpret_cast<int*>(myFactory.create("int"));
*myInt = 10;
std::cout<< *myInt << std::endl;
delete myInt;
myFactory.releaseTable();
return 0;
}
Would you consider Boost.MPL? Unlike STL, it allows creation of containers containing types, not instances. Having a map from string to a type would give you desired factory, isn't it?
I'm trying to implement a superclass in c++ that would implement one method:
-void setValueForKey(void *value, string key);
all this method would have to do is to set the value of a property associated with a given key to the new value.
This would be easy in a language that implements introspection mechanisms; as far as I know C++ doesn't.
In order to accomplish this I created another method:
void registerKeyForProperty(void *propertyPtr, string key);
all this method does is it stores in and internal map a pointer to a property associated with a given key, so all my subclasses would call this for every property they declare and I would have a way of setting values for properties without necessity to use the setters.(That's what I need!) (I explain why at the end of the post...)
for this second function I have the following implementation:
void registerKeyForProperty(void *propertyPtr, string key){
_keysDictionary->insert(pair<string,void*>(key,property));
}
where _keysDictionary is a stl map.
for the first one I have the following implementation:
void ConstructableObject::setValueForKey(void* value, string key) {
map<string,void *>::iterator it=_keysDictionary->find(key);
if(it==_keysDictionary->end()){return;}//just return if there is nothing for that key
void *property=it->second;
(*property)=value;
}
the problem is the last line is not legal C++ because ofcourse I cannot just deference that void*.
My questions are:
Is there any other way of implementing the desired functionality?
Is there a "legal" way of doing this the way I am doing it? (I cannot simply use a reinterpret_cast cause I don't know what to cast to...)
Why this:
I need to parse and xml file that has some information about some objects. I'll be using TinyXML and therefore I'll have the atribute names for the objects and their values. That would be how I would like to use it:
MyClass obj();//the constructor would call setValueForKey(...,...) for every property so all are now registered
for every attribute{
obj.setValueForKey(attribute.value,attribute.name);
}
//all properties should be set now
If the key exists, why not simply do
_keysDictionary[key] = value;
Or if you want to use the iterator
it->second = value;
It could be done with using of the type awareness techniques and for example The Memento Pattern is one of choices. The following code could be extended with the some macro stuff that generating the unique keys based on the attribute pointer signature:
class introspection
{
public:
template <typename Class, typename Member>
void registerKey(std::string key, Member Class::*memberPointee, Class* classPointee)
{
typedef member_setter<Class, Member> hold_member_pointer;
base_setter* setter = new hold_member_pointer(memberPointee, classPointee);
keys.insert(std::make_pair(key, setter));
}
template <typename Value>
void setValue(std::string key, Value value)
{
if ( keys.count(key) > 0 )
{
keys[key]->set(value);
}
else
{
throw std::logic_error("no such key");
}
}
private:
struct base_setter
{
virtual void set(boost::any value) = 0;
}; // struct base_setter
template <typename Class, typename Member>
struct member_setter : base_setter
{
member_setter(Member Class::*memberPointee, Class* classPointee)
: memberPointee(memberPointee)
, classPointee(classPointee) {}
void set(boost::any value) override
{
Member newValue = boost::any_cast<Member>(value);
classPointee->*memberPointee = newValue;
}
Member Class::*memberPointee;
Class* classPointee;
}; // struct member_setter
std::map<std::string, base_setter*> keys;
}; // class introspection
struct Data
{
int value;
}; // struct Data
int main()
{
introspection i;
Data d;
d.value = 100;
i.registerKey("value", &Data::value, &d);
i.setValue("value", 200); // OK
i.setValue("value", "not valid"); // bad_any_cast
}
The one thing that could be (not so easily) improved here is provide the compile-time type check for setValue, instead of runtime any_cast casting.
Make setValueForKey be a templated function instead of a function that accepts a void pointer. That way, you can know about the type information of the property long enough to create a templated setter
class BaseSetter
{
public:
virtual void set(void* inValue) = 0;
}
template <typename T>
class SpecializedSetter
{
public:
SpecializedSetter(T* inMyValue)
: mValue(inValue)
{ }
virtual void set(void* inValue)
{
*mValue = *reinterpret_cast<T*>(inValue);
}
private:
T* mValue;
}
template <typename T>
void registerKeyForProperty(T* inValue, string inKey)
{
registerSetterForProperty(new SpecificSetter<T>(inValue), inKey);
}
This, however, assumes inValue is a pointer to the same type of data as the value on the class. To make that safe, consider boost::any or defining some other type which contains the type information from the XML file and using that rather than void*
I have a factory class to build objects of base class B.
The object (D) that uses this factory receives a list of strings representing the actual types.
What is the correct implementation:
the factory receives an Enum (and uses switch inside the Create function) and D is responsible to convert the string to Enum.
the factory receives a string and checks for a match to a set of valid strings (using ifs')
other implementation i didn't think of.
I would separate the conversion of strings to enum into a distinct object. This can easily be solved by a map btw. But error handling etc. is still something which neither D nor the factory should be worried about.
Then either D calls the converter to get its enum, or it is already converted beforehand, so D only needs to pass the enum to the factory. (Btw the factory would better use a map too instead of a switch internally).
This raises the question: do you actually need the enums at all (in places other than D and the factory)? If not, maybe the enum could be left out of the picture and you could use a map to convert directly from strings to types (i.e. - since C++ doesn't support dynamic class loading - to function objects which create the necessary concrete type instances for you). A rough example (I don't have an IDE to test it so bear with me if there are any errors in it):
// Function type returning a pointer to B
typedef (B*)(*func)() StaticConstructor;
// Function creating instances of subclass E
B* createSubclassE() {
return new E(...);
}
// Function creating instances of subclass F
B* createSubclassF() {
return new F(...);
}
// Mapping from strings to constructor methods creating specific subclasses of B
map<string, StaticConstructor> factoryMap;
factoryMap["E"] = &createSubclassE;
factoryMap["F"] = &createSubclassF;
Of course, the created instances should also be disposed of properly - in production code, the returned objects could be e.g. enclosed in an auto_ptr. But I hope this short example is enough to show you the basic idea. Here is a tutorial if you want more...
You can put all matching strings in the set or list and check if it contains your strings instead of writing ifs/switches.
My project on VC++/Qt had a large number of XML files containing strings that had a Enum representation into the source.
So for each Enum we had a wrapper with overloaded operator QString <> Enum:
enum DataColumnTypeEnum
{
DataColumnTypeNotSet,
ColumnBinary,
ColumnBoolean,
ColumnDate,
ColumnDateTime,
ColumnNumber,
ColumnFloat,
ColumnPrimary,
ColumnString,
ColumnText,
};
class DataColumnType
{
public:
DataColumnType();
DataColumnType(DataColumnTypeEnum);
DataColumnType(const QString&);
DataColumnType& operator = (DataColumnTypeEnum);
DataColumnType& operator = (const QString&);
operator DataColumnTypeEnum() const;
operator QString() const;
private:
DataColumnTypeEnum type;
};
DataColumnType& DataColumnType::operator = (const QString& str)
{
str.toLower();
if(str.isEmpty()) type = DataColumnTypeNotSet;
else if(str == "binary") type = ColumnBinary;
else if(str == "bool") type = ColumnBoolean;
else if(str == "date") type = ColumnDate;
else if(str == "datetime") type = ColumnDateTime;
else if(str == "number") type = ColumnNumber;
else if(str == "float") type = ColumnFloat;
else if(str == "primary") type = ColumnPrimary;
else if(str == "string") type = ColumnString;
else if(str == "text") type = ColumnText;
return *this;
}
but the approach in last listing is very ugly.
Better to create a static hash table or dictionary and look up into.
The normal way is to have your factory as a singleton. Then each class based on class B registers it's create function and name with the factory at static initialisiation time. This is often done with macros. The factory then can creates a fast hash table of these name to create functions. Etc... you get the drift.
I personally use an enhanced enum because I've always found the enum of C++ lacking: messages like Type 3 - method -begin aren't much informative.
To this way, I use a simple templated class:
template <class Holder>
class Enum
{
public:
typedef typename Holder::type enum_type;
Enum(): mValue(Invalid()) {}
Enum(enum_type i): mValue(Get(i)) {}
explicit Enum(const std::string& s): mValue(Get(s)) {}
bool isValid() const { return mValue != Invalid(); }
enum_type getValue() const { return mValue->first; }
private:
typedef typename Holder::mapping_type mapping_type;
typedef typename mapping_type::const_iterator iterator;
static const mapping_type& Mapping() { static mapping_type MMap = Holder::Initialize(); return MMap; }
static iterator Invalid() { return Mapping().end(); }
static iterator Get(enum_type i) { // search }
static iterator Get(const std::string& s) { // search }
iterator mValue;
};
You define Holder like so:
struct Example
{
typedef enum {
Value1,
Value2,
Value3
} type;
typedef std::vector< std::pair< type, std::string > > mapping_type;
static mapping_type Initialize() {
return builder<mapping_type>()(Value1,"Value1")(Value2,"Value2")(Value3,"Value3");
}
};
You can define a macro for it:
DEFINE_ENUM(Example, (Value1)(Value2)(Value3))
But I let the implementation as an exercise (Boost.Preprocessor is your friend).
The cool thing is to use it!
int main(int argc, char* argv[])
{
std::string s;
std::cin >> s;
Enum<Example> e(s);
switch(e.getValue())
{
case Example::Value1:
case Example::Value2:
++e;
case Example::Value3:
std::cout << e << std::endl;
default:
}
}
I want to fill a map with class name and method, a unique identifier and a pointer to the method.
typedef std::map<std::string, std::string, std::string, int> actions_type;
typedef actions_type::iterator actions_iterator;
actions_type actions;
actions.insert(make_pair(class_name, attribute_name, identifier, method_pointer));
//after which I want call the appropriate method in the loop
while (the_app_is_running)
{
std::string requested_class = get_requested_class();
std::string requested_method = get_requested_method();
//determine class
for(actions_iterator ita = actions.begin(); ita != actions.end(); ++ita)
{
if (ita->first == requested_class && ita->second == requested_method)
{
//class and method match
//create a new class instance
//call method
}
}
}
If the method is static then a simple pointer is enough and the problem is simple,
but I want to dynamically create the object so I need to store a pointer to class and an offset for the method and I don't know if this works (if the offset is always the same etc).
The problem is that C++ lacks reflection, the equivalent code in a interpreted language with reflection should look like this (example in PHP):
$actions = array
(
"first_identifier" => array("Class1","method1"),
"second_identifier" => array("Class2","method2"),
"third_identifier" => array("Class3","method3")
);
while ($the_app_is_running)
{
$id = get_identifier();
foreach($actions as $identifier => $action)
{
if ($id == $identifier)
{
$className = $action[0];
$methodName = $action[1];
$object = new $className() ;
$method = new ReflectionMethod($className , $methodName);
$method -> invoke($object);
}
}
}
PS: Yes I'm trying to make a (web) MVC front controller in C++.
I know I know why don't use PHP, Ruby, Python (insert your favorite web language here) etc?, I just want C++.
Perhaps you're looking for member function pointers.
Basic usage:
class MyClass
{
public:
void function();
};
void (MyClass:*function_ptr)() = MyClass::function;
MyClass instance;
instance.*function_ptr;
As stated in the C++ FAQ Lite, macros and typedefs would greatly increase readability when using member function pointers (because their syntax isn't common in code).
I wrote that stuff last hours, and added it to my collection of useful stuff. The most difficult thing is to cope with the factory function, if the types you want to create are not related in any way. I used a boost::variant for this. You have to give it a set of types you ever want to use. Then it will keep track what is the current "active" type in the variant. (boost::variant is a so-called discriminated union). The second problem is how you store your function pointers. The problem is that a pointer to a member of A can't be stored to a pointer to a member of B. Those types are incompatible. To solve this, i store the function pointers in an object that overloads its operator() and takes a boost::variant:
return_type operator()(variant<possible types...>)
Of course, all your types' functions have to have the same return type. Otherwise the whole game would only make little sense. Now the code:
#include <boost/variant.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/function_arity.hpp>
#include <boost/preprocessor/repetition.hpp>
#include <map>
#include <string>
#include <iostream>
// three totally unrelated classes
//
struct foo {
std::string one() {
return "I ";
}
};
struct bar {
std::string two() {
return "am ";
}
};
struct baz {
std::string three() const {
return "happy!";
}
};
// The following are the parameters you have to set
//
// return type
typedef std::string return_type;
// variant storing an object. It contains the list of possible types you
// can store.
typedef boost::variant< foo, bar, baz > variant_type;
// type used to call a function on the object currently active in
// the given variant
typedef boost::function<return_type (variant_type&)> variant_call_type;
// returned variant will know what type is stored. C++ got no reflection,
// so we have to have a function that returns the correct type based on
// compile time knowledge (here it's the template parameter)
template<typename Class>
variant_type factory() {
return Class();
}
namespace detail {
namespace fn = boost::function_types;
namespace mpl = boost::mpl;
// transforms T to a boost::bind
template<typename T>
struct build_caller {
// type of this pointer, pointer removed, possibly cv qualified.
typedef typename mpl::at_c<
fn::parameter_types< T, mpl::identity<mpl::_> >,
0>::type actual_type;
// type of boost::get we use
typedef actual_type& (*get_type)(variant_type&);
// prints _2 if n is 0
#define PLACEHOLDER_print(z, n, unused) BOOST_PP_CAT(_, BOOST_PP_ADD(n, 2))
#define GET_print(z, n, unused) \
template<typename U> \
static variant_call_type get( \
typename boost::enable_if_c<fn::function_arity<U>::value == \
BOOST_PP_INC(n), U>::type t \
) { \
/* (boost::get<actual_type>(some_variant).*t)(n1,...,nN) */ \
return boost::bind( \
t, boost::bind( \
(get_type)&boost::get<actual_type>, \
_1) BOOST_PP_ENUM_TRAILING(n, PLACEHOLDER_print, ~) \
); \
}
// generate functions for up to 8 parameters
BOOST_PP_REPEAT(9, GET_print, ~)
#undef GET_print
#undef PLACEHOLDER_print
};
}
// incoming type T is a member function type. we return a boost::bind object that
// will call boost::get on the variant passed and calls the member function
template<typename T>
variant_call_type make_caller(T t) {
return detail::build_caller<T>::template get<T>(t);
}
// actions stuff. maps an id to a class and method.
typedef std::map<std::string,
std::pair< std::string, std::string >
> actions_type;
// this map maps (class, method) => (factory, function pointer)
typedef variant_type (*factory_function)();
typedef std::map< std::pair<std::string, std::string>,
std::pair<factory_function, variant_call_type>
> class_method_map_type;
// this will be our test function. it's supplied with the actions map,
// and the factory map
std::string test(std::string const& id,
actions_type& actions, class_method_map_type& factory) {
// pair containing the class and method name to call
std::pair<std::string, std::string> const& class_method =
actions[id];
// real code should take the maps by const parameter and use
// the find function of std::map to lookup the values, and store
// results of factory lookups. we try to be as short as possible.
variant_type v(factory[class_method].first());
// execute the function associated, giving it the object created
return factory[class_method].second(v);
}
int main() {
// possible actions
actions_type actions;
actions["first"] = std::make_pair("foo", "one");
actions["second"] = std::make_pair("bar", "two");
actions["third"] = std::make_pair("baz", "three");
// connect the strings to the actual entities. This is the actual
// heart of everything.
class_method_map_type factory_map;
factory_map[actions["first"]] =
std::make_pair(&factory<foo>, make_caller(&foo::one));
factory_map[actions["second"]] =
std::make_pair(&factory<bar>, make_caller(&bar::two));
factory_map[actions["third"]] =
std::make_pair(&factory<baz>, make_caller(&baz::three));
// outputs "I am happy!"
std::cout << test("first", actions, factory_map)
<< test("second", actions, factory_map)
<< test("third", actions, factory_map) << std::endl;
}
It uses pretty fun techniques from boost preprocessor, function types and bind library. Might loop complicated, but if you get the keys in that code, it's not much to grasp anymore. If you want to change the parameter count, you just have to tweak variant_call_type:
typedef boost::function<return_type (variant_type&, int)> variant_call_type;
Now you can call member functions that take an int. Here is how the call side would look:
return factory[class_method].second(v, 42);
Have fun!
If you now say the above is too complicated, i have to agree with you. It is complicated because C++ is not really made for such dynamic use. If you can have your methods grouped and implemented in each object you want create, you can use pure virtual functions. Alternatively, you could throw some exception (like std::runtime_error) in the default implementation, so derived classes do not need to implement everything:
struct my_object {
typedef std::string return_type;
virtual ~my_object() { }
virtual std::string one() { not_implemented(); }
virtual std::string two() { not_implemented(); }
private:
void not_implemented() { throw std::runtime_error("not implemented"); }
};
For creating objects, a usual factory will do
struct object_factory {
boost::shared_ptr<my_object> create_instance(std::string const& name) {
// ...
}
};
The map could be composed by a map mapping IDs to a pair of class and function name (the same like above), and a map mapping that to a boost::function:
typedef boost::function<my_object::return_type(my_object&)> function_type;
typedef std::map< std::pair<std::string, std::string>, function_type>
class_method_map_type;
class_method_map[actions["first"]] = &my_object::one;
class_method_map[actions["second"]] = &my_object::two;
Calling the function would work like this:
boost::shared_ptr<my_object> p(get_factory().
create_instance(actions["first"].first));
std::cout << class_method_map[actions["first"]](*p);
Of course, with this approach, you loose flexibility and (possibly, haven't profiled) efficiency, but you greatly simplify your design.
I think the most important thing to find out here is, do all of your methods have the same signature? If they do, this is a trivial use of boost bind(if you're into that), functors are an option(the static, duck type kind), or just plain ole virtual inheritance is an option. Inheritance isnt currently in vogue but its pretty easy to understand and I dont think it complicates things anymore then using boost bind(imho best for small non systemic functors).
here is a sample implementation
#include<iostream>
#include<map>
#include<string>
using std::map;
using std::string;
using std::cout;
using std::pair;
class MVCHandler
{
public:
virtual void operator()(const string& somekindofrequestinfo) = 0;
};
class MyMVCHandler : public MVCHandler
{
public:
virtual void operator()(const string& somekindofrequestinfo)
{
cout<<somekindofrequestinfo;
}
};
void main()
{
MyMVCHandler myhandler;
map<string, MVCHandler*> handlerMap;
handlerMap.insert(pair<string, MVCHandler*>("mysuperhandler", &myhandler));
(*handlerMap["mysuperhandler"])("somekindofrequestdata");
}
Like many C++ questions, this looks like another application of Boost. You basically want to store the result of boost::bind(&Class::member, &Object). [edit] Storing such a result is easy with boost::function.
You can try using factory or abstract factory design patterns for the class, and a function pointer for the function.
I found the following 2 web pages with implementations when I was searching for solutions for a similar problem:
Factory
Abstract factory
If you do not want to use member function pointers, you can use statics which take an argument of the class instance. For example:
class MyClass
{
public:
void function();
static void call_function(MyClass *instance); // Or you can use a reference here.
};
MyClass instance;
MyClass::call_function(&instance);
This requires more work on the coder and causes maintainability issues (since if you update the signature of one, you must update that of the other as well).
You could also use a single static function which calls all your member functions:
class MyClass
{
public:
enum Method
{
fp_function,
};
void function();
static void invoke_method(MyClass *instance, Method method); // Or you can use a reference here.
};
void MyClass::invoke_method(MyClass *instance, Method method)
{
switch(method)
{
default:
// Error or something here.
return;
case fp_function:
instance->function();
break;
// Or, if you have a lot of methods:
#define METHOD_CASE(x) case fp_##x: instance->x(); break;
METHOD_CASE(function);
#undef METHOD_CASE
}
// Free logging! =D
}
MyClass instance;
MyClass::invoke_method(instance, MyClass::fp_function);
You can also use dynamic loading of the functions:
Use GetProcAddress in Windows, and dlsym in Unix.
Go for Subject-Observer design pattern.