How to access derived objects in base class container without direct inheritance - c++

I know I can cast pointer to base class in a container to pointer to derived class with the help of static_cast<derived_class*>(base_class_ptr).
However what can I do if they are not directly related, but only have a common child.
Look at the following example:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
class Item
{
public:
Item(std::string name): _name(name) { /* */ };
private:
std::string _name;
};
class Readable
{
public:
Readable(std::string content): _content(content) { /* */ };
virtual auto content(void) const -> std::string
{
return this->_content;
}
private:
std::string _content;
};
class Book: public Item, public Readable
{
public:
Book(std::string name, std::string content): Item(name), Readable(content) { /* */ };
};
class Person
{
public:
auto read(const Readable& readable) const noexcept
{
std::cout << readable.content() << '\n';
}
};
int main(void)
{
auto i0 = std::make_unique<Item>("Pot");
auto i1 = std::make_unique<Item>("Shoe");
auto b0 = std::make_unique<Book>("Death of a Salesman", "Blablablabla...");
std::vector<std::unique_ptr<Item>> container;
container.emplace_back(std::move(i0));
container.emplace_back(std::move(i1));
container.emplace_back(std::move(b0));
Person jonnie{};
jonnie.read(static_cast<Readable*>(container[2].get())) // Error!
}
I want to read a Book from the Items container, and that should be ok, because it is inherits from Readable, but I can't, because the compiler complains:
static_cast from 'pointer' (aka 'Item *') to 'Readable *', which are not related by inheritance, is not allowed
What can I do in such a case? Is there a clean solution?

You are looking to cast objects around that are required to be polymorphic; they require a virtual method. The easiest (and I think in this case the best) is to make the destructor virtual for all the base classes, e.g.;
class Item
{
public:
virtual ~Item() { /* */ };
// .. the rest of the class
};
This allows dynamic_cast<> to work at runtime (it works with polymorphic types), it will check for and cast the object appropriately. One caveat here (given the sample use in the OP) is that you will almost certainly have to check the return value against nullptr to check the cast succeeded.

If you want to read a Book, you should cast it to a Book (which is derived from Item).
The Book can then be used as a Readable, beacuse it is. But the Item is not.

Related

How can I get the value back from a templated parent class without knowing the underlying type?

Given these definitions and some code along these lines for illustration purposes:
class Child
{
private:
std::string name;
public:
Child(const std::string & name) name(name)
{ }
}
template<typename T>
class Parent : public Child
{
private:
T data;
public Parent(const std::string & name, const T & data) : Child(name), data(data)
{ }
inline GetData() const
{
return this->data;
}
}
std::vector<std::unique_ptr<Child>> values;
values.emplace_back(std::make_unique<Parent<int>>("value a", 4));
values.emplace_back(std::make_unique<Parent<std::string>>("value b", "test"));
for (const auto & v : values)
{
// I want to access the int and string here!
}
How would I determine the type used in the parent class from the base class here?
The concrete scenario I am working with is actually that I have a bunch of SqlParameterBase classes which contain information about SQL parameters for stored procedures and a SqlParameter<T> template that is supposed to be contained in a std::vector<std::unique_ptr<SqlParameterBase>> and passed into a class that represents a stored procedure configuration, so that it can be called.
But the fundamental problem here is that I need access to the underlying data and I wanted to avoid defining a void * in the base class to contain a pointer to the data. I'd prefer it to be as type safe as possible.
I'm open to alternative designs or approaches to solving this problem as well, so please feel free to suggest something entirely different if you feel it's better.
You want Child promise functionality (returning typed data) that only exists in derived types. Under inheritance, this is abstract functionality. So a set of speculative virtual accessors. upcasts aren't really required here.
I would say. If you don't want Child to promise what it returns, just that it returns something then it seems like your interface is too broad, you are putting the interface in the code that consumes the interface instead, say with speculative casts etc.
Either a set of Child's can be interfaced with though the interface defined in Child or they have some special functionality only available in Derived and must be spoken to that way.
As a wee addendum, you might consider a std::vector<std::variant<type1, type2, ...>> instead of completely erroding the type information in the container? std::variant is C++17 ofc so may not be suitable, but there are 3rd party implementations - boost variant etc.
Try this program (for the question: How would I determine the type used in the parent class from the base class here?):
The output prints the types..
But some more work is needed to look better
value a of type:i
value b of type:NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Here "i" means integer in the first line.
The second one has "basic_string" in it. But some junk around it.
I am posting this because, it may trigger better ideas.
Added comments for the code modified.
//g++ 5.4.0
#include <iostream>
#include <string>
#include <vector>
#include <memory>
//CREATED ANOTHER VARIABLE AND FUNCTION FOR TYPENAME.
//MODIFIED CONSTRUCTOR ACCORDINGLY.
class Child
{
private:
std::string name;
std::string tyName;
public:
Child(const std::string & name,const std::string &tyname):name(name), tyName (tyname)
{ }
std::string getName()
{
return name;
}
std::string getTypeName()
{
return tyName;
}
};
//MODIFIED CONSTRUCTOR TO PASS THE TYPENAME TO PARENT CLASS.
template<typename T>
class Parent : public Child
{
private:
T data;
public:
Parent(const std::string & name, const T & data) : Child(name,typeid(data).name()), data(data)
{ }
inline T GetData() const
{
return this->data;
}
};
int main()
{
std::vector<std::unique_ptr<Child>> values;
values.emplace_back(std::make_unique<Parent<int>>("value a", 4));
values.emplace_back(std::make_unique<Parent<std::string>>("value b", "test"));
//GET THE POINTER OF YOUR BASE CLASS.
//PRINT THE TYPE NAME.
for (const auto & v : values)
{
Child *p = dynamic_cast<Child*>(v.get());
std::cout<<p->getName()<<" of type:"<<p->getTypeName()<<std::endl;
}
return 0;
}

C++ class that can hold one of a set of classes that all inherit from a common class

What are the ways in C++ to handle a class that has ownership of an instance of another class, where that instance could potentially be of a number of classes all of which inherit from a common class?
Example:
class Item { //the common ancestor, which is never used directly
public:
int size;
}
class ItemWidget: public Item { //possible class 1
public:
int height;
int width;
}
class ItemText: public Item { //possible class 2
std::string text;
}
Let's say there is also a class Container, each of which contains a single Item, and the only time anyone is ever interested in an Item is when they are getting it out of the Container. Let's also say Items are only created at the same time the Container is created, for the purpose of putting them in the Container.
What are the different ways to structure this? We could make a pointer in Container for the contained Item, and then pass arguments to the constructor of Container for what sort of Item to call new on, and this will stick the Items all in the heap. Is there a way to store the Item in the stack with the Container, and would this have any advantages?
Does it make a difference if the Container and Items are immutable, and we know everything about them at the moment of creation, and will never change them?
A correct solution looks like:
class Container {
public:
/* ctor, accessors */
private:
std::unique_ptr<Item> item;
};
If you have an old compiler, you can use std::auto_ptr instead.
The smart pointer ensures strict ownership of the item by the container. (You could as well make it a plain pointer and roll up your own destructor/assignment op/copy ctor/move ctor/ move assignment op/ etc, but unique_ptr has it all already done, so...)
Why do you need to use a pointer here, not just a plain composition?
Because if you compose, then you must know the exact class which is going to be composed. You can't introduce polymorphism. Also the size of all Container objects must be the same, and the size of Item's derived classes may vary.
And if you desperately need to compose?
Then you need as many variants of Container as there are the items stored, since every such Container will be of different size, so it's a different class. Your best shot is:
struct IContainer {
virtual Item& getItem() = 0;
};
template<typename ItemType>
struct Container : IContainer {
virtual Item& getItem() {
return m_item;
}
private:
ItemType m_item;
};
OK, crazy idea. Don't use this:
class AutoContainer
{
char buf[CRAZY_VALUE];
Base * p;
public:
template <typename T> AutoContainer(const T & x)
: p(::new (buf) T(x))
{
static_assert(std::is_base_of<Base, T>::value, "Invalid use of AutoContainer");
static_assert(sizeof(T) <= CRAZY_VAL, "Not enough memory for derived class.");
#ifdef __GNUC__
static_assert(__has_virtual_destructor(Base), "Base must have virtual destructor!");
#endif
}
~AutoContainer() { p->~Base(); }
Base & get() { return *p; }
const Base & get() const { return *p; }
};
The container requires no dynamic allocation itself, you must only ensure that CRAZY_VALUE is big enough to hold any derived class.
the example code below compiles and shows how to do something similar to what you want to do. this is what in java would be called interfaces. see that you need at least some similarity in the classes (a common function name in this case). The virtual keyword means that all subclasses need to implement this function and whenever that function is called the function of the real class is actually called.
whether the classes are const or not doesn't harm here. but in general you should be as const correct as possible. because the compiler can generate better code if it knows what will not be changed.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class outputter {
public:
virtual void print() = 0;
};
class foo : public outputter {
public:
virtual void print() { std::cout << "foo\n"; }
};
class bar : public outputter {
public:
virtual void print() { std::cout << "bar\n"; }
};
int main(){
std::vector<outputter *> vec;
foo *f = new foo;
vec.push_back(f);
bar *b = new bar ;
vec.push_back(b);
for ( std::vector<outputter *>::iterator i =
vec.begin(); i != vec.end(); ++i )
{
(*i)->print();
}
return 0;
}
Output:
foo
bar
Hold a pointer (preferably a smart one) in the container class, and call a pure virtual clone() member function on the Item class that is implemented by the derived classes when you need to copy. You can do this in a completely generic way, thus:
class Item {
// ...
private:
virtual Item* clone() const = 0;
friend Container; // Or make clone() public.
};
template <class I>
class ItemCloneMixin : public Item {
private:
I* clone() const { return new I(static_cast<const I&>(*this); }
};
class ItemWidget : public ItemCloneMixin<ItemWidget> { /* ... */ };
class ItemText : public ItemCloneMixin<ItemText> { /* ... */ };
Regarding stack storage, you can use an overloaded new that calls alloca(), but do so at your peril. It will only work if the compiler inlines your special new operator, which you can't force it to do (except with non-portable compiler pragmas). My advice is that it just isn't worth the aggravation; runtime polymorphism belongs on the heap.

Dynamically creating an instance of a class from a string containing the class name in C++

Lets say I have a base class with 100 children:
class Base {
virtual void feed();
...
};
class Child1 : public Base {
void feed(); //specific procedure for feeding Child1
...
};
...
class Child100 : public Base {
void feed(); //specific procedure for feeding Child100
...
};
At runtime I want to read a file that contains which children to create and feed. Lets say I've read the file and the vector of strings "names" contains the names of the child classes (ie. Child1, Child4, Child99). Now I'm going to iterate through these strings, create an instance of the specific child, and feed it with its specific feeding procedure:
vector<Base *> children;
for (vector<string>::iterator it = names.begin(); it != names.end(); ++it) {
Base * child = convert_string_to_instance(*it)
child->feed()
children.push_back(child);
}
How would I create the function convert_string_to_instance() such that if it takes in the string "Child1" it returns a "new Child1", if the string argument is "Child4" it returns a "new Child4", etc
<class C *> convert_string_to_instance(string inName) {
// magic happens
return new C; // C = inName
// <brute force?>
// if (inName == "Child1")
// return new Child1;
// if (inName == "Child2")
// return new Child2;
// if (inName == "Child3")
// return new Child3;
// </brute force>
}
C++ does not provide a method for dynamic construction of class instances like this. However, you may be able to use code generation to generate the "brute force" code (like you showed above) from a list of classes. Then, #include the generated code in your convert_string_to_instance method.
You can also set up your project build system to rebuild the generated code anytime the list of classes changes.
I asked a question entitled automatic registration of object creator function with a macro that has the following example program that runs:
#include <map>
#include <string>
#include <iostream>
struct Object{ virtual ~Object() {} }; // base type for all objects
struct ObjectFactory {
static Object* create(const std::string& id) { // creates an object from a string
const Creators_t::const_iterator iter = static_creators().find(id);
return iter == static_creators().end() ? 0 : (*iter->second)(); // if found, execute the creator function pointer
}
private:
typedef Object* Creator_t(); // function pointer to create Object
typedef std::map<std::string, Creator_t*> Creators_t; // map from id to creator
static Creators_t& static_creators() { static Creators_t s_creators; return s_creators; } // static instance of map
template<class T = int> struct Register {
static Object* create() { return new T(); };
static Creator_t* init_creator(const std::string& id) { return static_creators()[id] = create; }
static Creator_t* creator;
};
};
#define REGISTER_TYPE(T, STR) template<> ObjectFactory::Creator_t* ObjectFactory::Register<T>::creator = ObjectFactory::Register<T>::init_creator(STR)
namespace A { struct DerivedA : public Object { DerivedA() { std::cout << "A::DerivedA constructor\n"; } }; }
REGISTER_TYPE(A::DerivedA, "A");
namespace B { struct DerivedB : public Object { DerivedB() { std::cout << "B::DerivedB constructor\n"; } }; }
REGISTER_TYPE(B::DerivedB, "Bee");
namespace C { struct DerivedC : public Object { DerivedC() { std::cout << "C::DerivedC constructor\n"; } }; }
REGISTER_TYPE(C::DerivedC, "sea");
namespace D { struct DerivedD : public Object { DerivedD() { std::cout << "D::DerivedD constructor\n"; } }; }
REGISTER_TYPE(D::DerivedD, "DEE");
int main(void)
{
delete ObjectFactory::create("A");
delete ObjectFactory::create("Bee");
delete ObjectFactory::create("sea");
delete ObjectFactory::create("DEE");
return 0;
}
compile and run output is:
> g++ example2.cpp && ./a.out
A::DerivedA constructor
B::DerivedB constructor
C::DerivedC constructor
D::DerivedD constructor
If you have a lot of classes, you'd usually choose a less brute force approach. A trie or hash_map between class names and factory functions is a good approach.
You can use a codegen approach as suggested by Greg to build this factory table, for example doxygen can parse your source code and output a list of all classes in xml format along with inheritance relationships, so you could easily find all classes deriving from a common "interface" base class.
It sounds like you might be using subclasses for things that should be encoded as fields.
Instead of coding the different behaviour in 100 classes, consider building a look-up table with rules/constants/function-pointers that allow you to implement the proper behaviour from one class.
For example, instead of:
class SmallRedSquare : public Shape {...};
class SmallBlueSquare : public Shape {...};
class SmallBlueCircle : public Shape {...};
class SmallRedCircle : public Shape {...};
class BigRedSquare : public Shape {...};
class BigBlueSquare : public Shape {...};
class BigBlueCircle : public Shape {...};
class BigRedCircle : public Shape {...};
try:
struct ShapeInfo
{
std::string type;
Size size;
Color color;
Form form;
};
class Shape
{
public:
Shape(std::string type) : info_(lookupInfoTable(type)) {}
void draw()
{
// Use info_ to draw shape properly.
}
private:
ShapeInfo* lookupInfoTable(std::string type) {info_ = ...;}
ShapeInfo* info_;
static ShapeInfo infoTable_[];
};
const ShapeInfo Shape::infoTable_[] =
{
{"SmallRedSquare", small, red, &drawSquare},
{"SmallBlueSquare", small, blue, &drawSquare},
{"SmallRedCircle", small, red, &drawCircle},
{"SmallBlueCircle", small, blue, &drawCircle},
{"BigRedSquare", big, red, &drawSquare},
{"BigBlueSquare", big, blue, &drawSquare},
{"BigBlueCircle", big, red, &drawCircle},
{"BigRedCircle", big, blue, &drawCircle}
}
int main()
{
Shape s1("SmallRedCircle");
Shape s2("BigBlueSquare");
s1.draw();
s2.draw();
}
This idea might not be applicable to your problem, but I figure it couldn't hurt to present it anyway. :-)
My idea is like the Replace Subclass with Fields refactoring, but I go a bit further.
You can abuse the preprocessor and set up some static class members that register your classes with a factory via a hash_map like Ben describes. If you have visual studio, look at how DECLARE_DYNCREATE is implemented in MFC. I've done something similar to implement a class factory. Non-standard for sure but since C++ does not offer any kind of support for this type of mechanism any solution is probably going be non-standard.
Edit
I said in a comment earlier I was working on documenting a scaled down version of something I had done. The scaled down version is still rather large so I posted it here. If there is enough interest I can copy/paste it on this site. Let me know.
This is the skeleton of a horrible, horrible way to do it:
class Factory {
public:
virtual Base * make() = 0;
};
template<typename T> class TemplateFactory : public Factory {
public:
virtual Base * make() {
return dynamic_cast<Base *>(new T());
}
};
map<string, Factory *> factories;
#define REGISTER(classname) factories[ #classname ] = new TemplateFactory<classname>()
Then call REGISTER(classname); for every relevant derived class of Base, and use factories["classname"]->make() to get a new object of type classname. Obvious flaws with the above code as written include massive potential for memory leaks, and the general awfulness of combining macros and templates.
Behold the mighty Boost.
The one thing you have to do in order to use my solution is to add a new member to all your classes, and that is a static const string that contains the name of the class. There are probably other ways to do it too, but that's what I have right now.
#include <iostream>
#include <vector>
#include <string>
#include <boost/fusion/container/list/cons.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/view/iterator_range.hpp>
using namespace std;
using boost::fusion::cons;
class Base { virtual void feed(){ } };
class Child1 : public Base{
void feed(){ }
public:
static const string name_;
};
const string Child1::name_ = "Child1";
class Child3 : public Base{
void feed(){ }
public:
static const string name_;
};
const string Child3::name_ = "Child3";
//...
class Child100 : public Base{
void feed(){ }
public:
static const string name_;
};
const string Child100::name_ = "Child100";
// This is probably the ugliest part, but I think it's worth it.
typedef cons<Child1, cons<Child3, cons<Child100> > > MyChildClasses;
typedef vector<Base*> Children;
typedef vector<string> Names;
struct CreateObjects{ // a.k.a convert_string_to_instance() in your example.
CreateObjects(Children& children, string name) : children_(&children), name_(name){ }
template <class T>
void operator()(T& cs) const{
if( name_ == cs.name_ ){
cout << "Created " << name_ << " object." << endl;
(*children_).push_back(new T);
}else{
cout << name_ << " does NOT match " << cs.name_ << endl;
}
}
Children* children_;
string name_;
};
int main(int argc, char* argv[]){
MyChildClasses myClasses;
Children children;
Names names;
names.push_back("Child1");
names.push_back("Child100");
names.push_back("Child1");
names.push_back("Child100");
// Extra test.
// string input;
// cout << "Enter a name of a child class" << endl;
// cin >> input;
// names.push_back(input);
using namespace boost::fusion;
using boost::fusion::begin;
using boost::fusion::for_each;
for(Names::iterator namesIt = names.begin(); namesIt != names.end(); ++namesIt){
// You have to know how many types there are in the cons at compile time.
// In this case I have 3; Child1, Child3, and Child100
boost::fusion::iterator_range<
result_of::advance_c<result_of::begin<MyChildClasses>::type, 0>::type,
result_of::advance_c<result_of::begin<MyChildClasses>::type, 3>::type
> it(advance_c<0 >(begin(myClasses)),
advance_c<3>(begin(myClasses)));
for_each(it, CreateObjects(children, *namesIt));
}
cout << children.size() << " objects created." << endl;
return 0;
}

it is possible to change return type when override a virtual function in C++?

I encounter a problems about override virtual functions, in fact,it is about hessian (a web service protocol).
it has a base class Object, and some derived classes : Long,Int,String,...,all derived classes has a no-virtual function "value"
class Object
{
...
};
class Long :public Object
{
...
public:
typedef long long basic_type;
basic_type value(){return value_;}
private:
basic_type value_;
...
};
class Int :public Object
{
...
public:
typedef int basic_type;
basic_type value(){return value_;}
private:
basic_type value_;
...
};
now I want to add a function ,say, toString ,which can convert Object to a string:
Object *obj = ...
cout<<obj->toString();
if I can change the value function to virtual ,I only need to write a toString function in Object, else, I need to write a virtual function toString, and to override this functions in all derived classes.
for example
class Object
{
virtual Type value(); // It seemed that I can't write a function like this,because the Type is different for different derived classes
std::string toString()
{
some_convert_function(value());
}
};
but I can't write a virtual value function because of return value can't be override.
is there any good solution for this issue?
Thanks
it is possible to change return type when override a virtual function in C++?
Only in a very limited way, in that (raw) pointer or reference return type can be covariant.
is there any good solution for this issue?
Well, there are two fairly good solutions, and one slightly bad solution.
I'm giving you the slightly bad solution here. One reason that I'm giving that is that it's easy to understand, or at least it's quite easy to "copy and modify" even if one doesn't quite understand it. Another reason is that one of the good solutions requires some extensive general support machinery that there's no room for discussing here, and the other good solution (the one that in my opinion is best in nearly every respect) is of a kind that, at least when I have presented that kind of solution, has automatically received drive-by downvotes and only that, here on SO. I guess that that's the price to pay for the diversity here, which diversity is a Very Good Thing :-) But, unfortunately it means that there's no point in offering the real good stuff, I'd be down to negative rep then.
Anyways, code, based on dominance in virtual inheritance; it's about the same as inheriting an implementation of an interface in Java or C#:
#include <iostream>
#include <string>
#include <sstream>
//--------------------------------------- Machinery:
class ToStringInterface
{
public:
virtual std::string toString() const = 0;
};
template< typename ValueProvider >
class ToStringImpl
: public virtual ToStringInterface
{
public:
virtual std::string toString() const
{
ValueProvider const& self =
*static_cast<ValueProvider const*>( this );
std::ostringstream stream;
stream << self.value();
return stream.str();
}
};
//--------------------------------------- Usage example:
class Object
: public virtual ToStringInterface
{
// ...
};
class Long
: public Object
, public ToStringImpl< Long >
{
public:
typedef long long BasicType;
Long( BasicType v ): value_( v ) {}
BasicType value() const { return value_; }
private:
BasicType value_;
};
class Int
: public Object
, public ToStringImpl< Int >
{
public:
typedef int BasicType;
Int( BasicType v ): value_( v ) {}
BasicType value() const { return value_; }
private:
BasicType value_;
};
int main()
{
Object const& obj = Int( 42 );
std::cout << obj.toString() << std::endl;
}
If your Long and Int classes etc. are very similar, as they seem to be, consider defining just one class template, or perhaps inherit from specializations of such a template (this might also help avoid bugs, since it reduces redundancy).
EDIT: I see now that you have accepted an answer that is essentially just my last suggestion about templating. That means that I've answered the question as posed (a solution for distinct, different classes) while you had something less general in mind. Oh well.
Cheers & hth.,
No, you can't write toString in Object using a virtual 'value' function and override the return type. However you can write a virtual toString and with a template programming trick accomplish almost the same thing.
class Object
{
public:
virtual std::string toString();
}
template < class ValueType >
class BasicType : Object
{
public:
typedef ValueType basic_type;
basic_type value() { return value_; }
std::string toString()
{
return some_convert_function( value_ );
}
private:
basic_type value_;
}
typedef BasicType<long long> Long;
typedef BasicType<int> Int;
Unfortunately you can't overload functions in C++ by return value. What you could do, if you have the appropriate some_convert_function in place for all types you need it for would be to create free a template function that looks something like this:
template<typename T>
std::string toString(T const& t)
{
return some_convert_function<T>(t);
}
You can't override a function with a different return type; the closest you can come is to hide a function in the parent with a different one in the derived class. But that's not what you want, because the two will be different functions, completely unrelated.
You were correct in assuming that you'd need to create a new toString function in each derived class - that's what polymorphism is all about.
I don't think you're going about this the right way. While it is possible in some circumstances to change the return type of a virtual function, consider this: How is your function being used? If it's virtual, changes are that users will be using the base class. As such, they are oblivious as to what the actual type of your class is, and thus they wouldn't know what type to expect. So:
Either return the base class type.
Return functions that give you the proper type (i.e virtual std::string getStringValue(), which gives you a string if applicable).
Use templates, if the type is known by the user.
Regarding #MerickOWA comment, here's another solution, that does not requires any additional template mechanism.
Since you intended to have a virtual "value()" method that you needed to implement in all classes, I've extended the idea (usually, in these kind of framework, you've plenty of similar "basic" methods, so I've used a macro to write them for me, it's not required, it's just faster and less error prone.
#include <iostream>
#include <string>
#include <sstream>
struct Object
{
std::string toString() const { std::ostringstream str; getValue(str); return str.str(); }
virtual void getValue(std::ostringstream & str) const { str<<"BadObj"; }
};
// Add all the common "basic & common" function here
#define __BoilerPlate__ basic_type value; void getValue(std::ostringstream & str) const { str << value; }
// The only type specific part
#define MAKE_OBJ(T) typedef T basic_type; __BoilerPlate__
struct Long : public Object
{
MAKE_OBJ(long long)
Long() : value(345) {}
};
struct Int : public Object
{
MAKE_OBJ(long)
Int() : value(3) {}
};
int main()
{
Object a;
Long b;
Int c;
std::cout<<a.toString()<<std::endl; // BadObj
std::cout<<b.toString()<<std::endl; // 345
std::cout<<c.toString()<<std::endl; // 3
return 0;
}
Obviously, the trick is in the std::ostringstream classes that's accept any parameter type (long long, long, etc...). Since this is standard C++ practice, it should not matter.

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;
}