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:
}
}
Related
I have a string variable which contains the name of the structure. This structure is declared in a header file. I would like to create an object of a structure based on the value of the structure name which is held in the string variable in C++.
struct myStruct{
int a;
char b;
};
string structName = "myStruct";
// Instantiate a structure variable [like this: "struct myStruct"]
Could anyone please help me with this?
The feature you're looking for is called introspection. This is something C++ has not. So you should fallback to, in this order:
Question your design
Write a hack
Here's an idea of a hack:
using result_type = /* some type, possibly void */;
std::unique_ptr<result_type> factory(std::string const& kind)
{
if (kind == "alice") return new alice;
if (kind == "bob") return new bob;
// ...
return nullptr;
}
It is not possible in C++ to create an instance of a class by name determined at runtime. C++ has very little ability to reflect.
You could however build the support for it yourself. The idea here is to create a map of name-string to a factory function which returns an instance of that type. The returned instance needs to be wrapped within std::any because C++ - as a strongly and statically typed language - cannot let the return type to be determined at runtime.
There is a function add_factory, which must be called for all types that you want to be able to instantiate using the name. There is also a helper macro, which like all macros, works because of magic.
auto& factories() {
static std::unordered_map<std::string, std::any(*)()> factories;
return factories;
}
template<class T>
void
add_factory(const char* name) {
// further development: take function as argument so that
// non-default-constructible classes can be supported
factories()[name] = []() -> std::any {
return T{};
};
}
std::any
create(const char* name)
{
const auto& f = factories();
if (f.find(name) != f.end())
return f.find(name)->second();
throw std::runtime_error("I haven't heard of this type");
}
// don't use this macro in header files
#define ADD_FACTORY(name) namespace { auto dummy_##name = (add_factory<name>(#name), 0); }
// ----- usage -----
struct a {
int i;
};
ADD_FACTORY(a)
struct b {
double d;
};
ADD_FACTORY(b)
// factories are not limited to classes
ADD_FACTORY(int)
int main()
{
std::any instance = create("a");
assert(std::any_cast<a>(&instance));
}
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
};
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 making a class for lazy initialization of a bunch of objects (not totally generic, all under my control). Only one object of each type will exist. I have a linear-time implementation using std::vector and boost::any already. Hopefully it should give a better idea of what I'm talking about.
I can make the assumption that all the objects I'll want to access have
typedef boost::shared_ptr<CLASSNAME> HandleType
in their definitions and they all have a constructor that takes the ObjectProvider by reference.
class ObjectProvider {
typedef std::vector<boost::any> ContainerType;
ObjectProvider() : container() {}
public:
// this is where the relevant method is
template <class TElementType>
typename TElementType::HandleType get() {
for (ContainerType::iterator it = container.begin(); it != container.end(); ++it) {
try {
return boost::any_cast<typename TElementType::HandleType>(*it);
} catch (boost::bad_any_cast &) {}
}
// failed to find it so create it
TElementType::HandleType handle = boost::make_shared<TElementType>(*this);
container.push_back(handle);
return handle;
}
private:
ContainerType container;
};
// ----- FOR TESTING -----
class SomeObject {
public:
SomeObject(ObjectProvider &) {}
typedef boost::shared_ptr<SomeObject> HandleType;
};
int main(int argc, char** argv) {
ObjectProvider provider;
// expensive creation is done here
SomeObject::HandleType obj1 = provider.get<SomeObject>();
// expensive creation is not re-done
SomeObject::HandleType obj2 = provider.get<SomeObject>();
assert (obj1 == obj2); // pointers should point to the same object
}
Some motivation: Many of these objects (they're clients for various services) require creating additional clients of various types, but I don't want to be recreating them each time. So the goal of this class is to provide a method of caching the already-created clients.
Here is my question:
Is there a better way to do this?
In particular, is there a way to avoid the loop in get<...>() and somehow key by type? I'd love to have constant-time access instead of linear time and the current method fails to make use of the type information available for lookup.
Just for a little additional explanation of what I'm thinking, I might do something like this in Java:
Map<Class<?>, Object> objMap;
public <T> T get(Class<T> class) {
Object obj = objMap.get(class);
if (obj != null) {
return (T)obj;
} else {
T newObj = ;// fiddle with java reflection to create a new instance
objMap.put(class, newObj);
}
}
If there is only one of each type, then you can use typeid to extract a string representing the type, and use that as a key to a map or unordered_map.
//...
typedef std::map<std::string, boost::any> ContainerType;
//...
template <class TElementType>
typename TElementType::HandleType get() {
std::string name = typeid(TElementType).name();
ContainerType::iterator it = container.find(name);
if (it != container.end()) {
try {
return boost::any_cast<typename TElementType::HandleType>(it->second);
} catch (boost::bad_any_cast &) {}
}
// failed to find it so create it
TElementType::HandleType handle = boost::make_shared<TElementType>(*this);
container[name] = handle;
return handle;
}
If you want a class to be instanciate only once, you are probably looking for the design pattern singleton.
Wikipedia definition:
In software engineering, the singleton pattern is a design pattern that restricts the Instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects. The term comes from the mathematical concept of a singleton.
Other links about singleton
C++ Singleton design pattern
Singleton: How should it be used
Can any one provide me a sample of Singleton in c++?
And you can find many more explanations on the internet about it.
If you are concerned about typeid() support, you can also add a class index yourself.
class SomeObject {
public:
SomeObject(ObjectProvider &) {}
typedef boost::shared_ptr<SomeObject> HandleType;
static const int ClassIndex = 0;
};
and the object provider becomes
class ObjectProvider {
typedef std::vector<boost::any> ContainerType;
public:
ObjectProvider() : container() {}
// this is where the relevant method is
template <class TElementType>
typename TElementType::HandleType get() {
int idx = TElementType::ClassIndex;
if (container.size() <= idx) {
container.resize(idx + 1);
}
// Check if object exists
if (container[idx].empty()) {
typename TElementType::HandleType handle = boost::make_shared<TElementType>(*this);
container[idx] = handle;
}
return boost::any_cast<typename TElementType::HandleType>(container[idx]);
}
private:
ContainerType container;
};
On the downside, you must make sure that different classes don't clash on the ClassIndex field.
If you want constant time access, you could create your own type-id:
class Registry
{
private:
static int get_id()
{
static int id = 0;
return id++;
}
template< typename T>
static int get_type_id()
{
const static int id = get_id();
return id;
}
std::vector<HandleType> handles;
HandleType make_handle( const Registry&r)
{
// do what you need to do to create a new handle.
}
public:
template<typename T>
HandleType get()
{
int id = get_type_id<T>();
if (id + 1 > handles.size())
{
handles.resize( id + 1, HandleType());
}
if (!handles[id])
{
handles[id] = make_handle( *this);
}
return handles[id];
}
};
EDIT: I see that I've essentially given the same answer as umlum, except that this answer also tries to automatically create a numerical id for each type.
I wrote a C++ template class, but I do not have the type to instantiate the class. Types are stored in a string format. So I have to do something like this:
if ( propType == "char") {
Property<char> pChar = ...
} else if ( propType == "int") {
Property<int> pChar = ...
} if ( propType == "double") {
Property<double> pChar = ...
}
I am not liking this if-else- loop, is there any way to avoid this, or any other solution to such problem?
Many ways, but it's impossible to choose a good one without knowing how you use it in your particular case.
As a demonstration:
Let us suppose that all Property<T> classes inherit from PropertyBase
Let us suppose that you initialize them by parsing the type from a string
Here is some code then:
using PropertyPtr = std::unique_ptr<PropertyBase>;
using Parser = std::function<PropertyPtr(std::string const&, std::string const&)>;
template <typename T>
PropertyPtr parse(std::string const& type, std::string const& value) {
T v = boost::lexical_cast<T>(value);
return PropertyPtr(new Property<T>(std::move(v)));
}
std::map<std::string, Parser> const parsers = {
std::make_pair("char", parse<char>),
std::make_pair("int", parse<int>),
std::make_pair("double", parse<double>)
};
void dummy(std::string const& type, std::string const& value) {
auto const it = parsers.find(type);
assert(it == parsers.end() && "No parser");
auto const& parser = it->second;
PropertyPtr property = parser(type, value);
// do something with property
}
Hope this helps.
There are a couple of considerations here.
Suppose you want to parse the file from disk, then based off of the type on disk you want to create an object. You handle these objects in a mostly indistinguishable way. There are a finite list of types you are working with.
The answer I'd use for this would be a boost::variant to store the data, and a map (like Matthiew's answer) that maps the name of the type to a reader (or parser) for the type. The reader then returns a boost::variant<int, double, char, string, etc>.
Code then interacts with the variant in a pseudo uniform way. Helper functions use boost functions to call functors to interact with the variant.
Ie, something like this:
typedef boost::variant<int, double> myVariant;
typedef std::function< myVariant( input_stream_type& ) > ValueParser;
ValueParser GetParser( std::string typename );
// ...
struct DoTypeSpecificWork
{
typedef void result_type;
void operator()( int ) { /* ... int code goes here */ }
void operator()( double ) { /* ... double code goes here */ }
};
ValueParser parser = GetParser( propType );
myVariant var = parser( input_stream );
boost::variant::apply_visitor( DoTypeSpecificWork(), var );
Another option is to have a base PropertyBase class that has abstract interfaces that are type agnostic. Then Property<T> child classes that implement those abstract interfaces for each type. Creating those Property<T> child classes could be done directly (forcing the parser to know about your Property class), or indirectly (ie, you take a variant and produce an appropriate Property<T>, which decouples to parsing code from your type abstraction).
Basically, you need to decide between type erasure, type abstraction and template based programming to deal with multiple types. They all have their own advantages.