C++: Field has incomplete type - c++

I am trying to implement the strategy design pattern as an exercise. My classes are pretty simple:
1) Fly.cpp
class Fly
{
public:
Fly();
bool fly();
};
class CanFly : public Fly
{
public:
bool fly()
{
return true;
}
};
class CantFly : public Fly
{
public:
bool fly()
{
return false;
}
};
2) Animal.cpp
class Fly;
class Animal
{
Fly myFly;
public:
Animal(Fly f);
void setFly(Fly f);
Fly getFly();
};
Animal::Animal(Fly f)
{
myFly = f;
}
void Animal::setFly(Fly f)
{
myFly = f;
}
Fly Animal::getFly()
{
return myFly;
}
3) Dog.cpp
#include <iostream>
using namespace std;
class Animal;
class Dog : public Animal
{
public:
Dog(Fly f);
};
Dog::Dog(Fly f)
{
setFly(f);
cout << "Dog : " << getFly().fly() << endl;
}
4) Bird.cpp
#include <iostream>
using namespace std;
class Animal;
class Bird : public Animal
{
public:
Bird(Fly f);
};
Bird::Bird(Fly f)
{
setFly(f);
cout << "Bird : " << getFly().fly() << endl;
}
5) AnimalTest.cpp
#include <iostream>
using namespace std;
class Dog;
class Bird;
class CanFly;
class CantFly;
int main()
{
Fly f1 = new CanFly();
Fly f2 = new CantFly();
Bird b(f1);
Dog d(f2);
return 0;
}
The error which I get upon building the code is :
Animal.cpp:5:6: error: field 'myFly' has incomplete type 'Fly'
Fly myFly;
^
Can anyone help me why?
Thanks

Incomplete type error means that compiler doesn't see definition of the class, only declaration.
If you create an object or if you pass an object by value then you need to provide a definition of the class to the compiler. You do create objects and pass them around by values hence you need to include definition of relevant classes you pass into cpp files.
But that is not what you really want to do.
Your intention is to employ polymorphism so you need to pass objects by reference or by pointer instead.
Your Animal class should be:
class Animal
{
Fly &myFly;
public:
Animal(Fly &f);
void setFly(Fly &f);
Fly const &getFly();
};
That way you can pass any of Fly, CanFly, or CantFly objects into Animal object.
You also need to reorganise your code. You need to separate class definitions into header files. For example:
//Animal.h
class Fly; <=== Declaration. OK here.
class Animal
{
Fly &myFly;
public:
Animal(Fly &f);
void setFly(Fly &f);
Fly const &getFly();
};
Then you need to include headers into cpp. Example:
#include "Animal.h"
class Dog : public Animal <=== Compiler needs definition of Animal here
{
public:
Dog(Fly f);
};
Note the difference between following definitions:
Fly Animal::getFly()
{
return myFly;
}
Returns a copy of object stored in myFly.
Fly const &Animal::getFly()
{
return myFly;
}
Returns a constant reference to an object myFly
Also, perhaps, you do not need Fly, CanFly, CantFly classes at all. Classes Bird, Dog already "know" if they can or cannot fly. Sure, you are doing an exercise but still Fly, CanFly, etc seem to be redundant and artificial here.

In order to use a class, its definition is required. A statement like
class Fly;
is not a definition, but merely a declaration. A class that has been declared cannot be used, but you can define pointers and references to such a class.
So, to get your code working, you should split the code into header files (.hpp) containing the class definitions and source files (.cpp) containing the (non-inline) definitions of any class members declared in the headers.
Moreover, you seem to want to use polymorphism, but forgot to declare the member bool Fly::fly() to be virtual. I think what you want is
// file Fly.hpp
struct Fly
{
virtual bool fly() const = 0;
};
struct CanFly : Fly
{
bool fly()
{ return true; }
};
struct CantFly : Fly
{
bool fly()
{ return false; }
};
and then
// file Animal.hpp
struct Fly; // forward declaration
struct Animal
{
const Fly*const myFly; // use pointer to forwardly declared class
// const data member is public (serves as getter)
bool fly() const;
protected:
Animal(Fly const&f);
// no setter: an Animal cannot change its flying behaviour
};
and
// file Animal.cpp
#include "Fly.hpp"
#include "Animal.hpp"
Animal::Animal(Fly const&f)
: myFly(&f) {}
bool Animal::fly() const
{ return myFly->fly(); } // polymorphic call
However, I don't like this pattern. The problem is that in order to define a Bird or a Dog as derived from Animal, you need to provide a reference to an actual CanFly and CantFly, respectively, to the constructor of their base Animal. Moreover, there is nothing that qualifies an Animal other than whether it can fly or not, so why have this class Animal (in addition to Fly)?

change your fly.cpp to fly.h, in Animal.cpp you should #include<fly.h> Or just define your myFly as a pointer Fly* myFly.

Related

C++ Inheritance (instantiating derived class inside base class)

class MainClass
{
string _ClassName;
public:
string MainClass(string _C)
{
_ClassName = _C;
}
SubClass s1;
};
class SubClass : public MainClass
{
public:
string Method_1()
{
return a;
}
string Method_2()
{
return a;
}
};
Why is SubClass s1 not working can someone tell me please what am i missing I'm new to OOP.
I want to instantiate SubClass object inside MainClass but it doesn't seems to work.
basically, my aim is to access SubClass functions when MainClass object is instantiated in Main method something like this:
int Main()
{
MainClass M1("test");
M1.s1.Method_1(); <--------- this
}
The first problem is, that the MainClass does not know a thing about SubClass when you're trying to instantiate the object.
You need to use a forward declaration and a pointer to make it work.
Header file:
class SubClass; //Forward declaration, allows pointer.
class MainClass
{
string _ClassName;
public:
MainClass(string _C); //No return type on constructor
~MainClass();
SubClass *s1; //Size: 4 Bytes on 32bit system
protected:
MainClass();
};
class SubClass : public MainClass
{
public:
string Method_1();
string Method_2();
};
CPP file:
#include "headerFile.h"
MainClass::MainClass(string _C) :
_ClassName(_C),
s1(new SubClass) //Class definition is now known.
{
}
MainClass::MainClass() : s1(nullptr) //Nullptr -> No new object, no infinite recursion.
{
}
MainClass::~MainClass()
{
delete s1; //Do not forget to clean up your pointer.
}
string SubClass::Method_1()
{
return "a";
}
string SubClass::Method_2()
{
return "a";
}
Call:
int main()
{
MainClass M1("test");
M1.s1->Method_1(); //-> to dereference the pointer.
}
The second problem, as Richard Critten has pointed out, is an infinite recursion, which will cause your program to crash very quickly.
Each time you instantiate a SubClass, you also create a subclass, which creates yet another MainClass etc.
To circumvent this, you'll need a protected constructor, which does NOT create the subclass member.
The third problem:
You are returning a in your methods, which suggests a variable.
If you meant to return 'a', you need to put them into quotation marks.
Finally, in order to get it to compile, you'll need to write Main with a small m (int main()), otherwise the linker will complain.
However, as Mr. 'Not a number' correctly stated, the above edits only make your code compile.
What you likely are actually after however would be using virtual functions, which can be overridden by sub classes to specialize the behavior.
An example code using actual inheritance:
Header file:
class MainClass
{
string _ClassName;
public:
MainClass(string _C); //No return type on constructor
virtual ~MainClass(); //All base classes that have at least one virtual method should also have a virtual destructor, even if it is empty.
virtual void doSomething();
};
class SubClass : public MainClass
{
public:
SubClass(string className);
void doSomething();
};
CPP file:
#include "headerFile.h"
#include <stdio.h>
MainClass::MainClass(string _C) : _ClassName(_C)
{
}
MainClass::~MainClass()
{}
void MainClass::doSomething()
{
printf("Called from MainClass\n");
}
SubClass::SubClass(string className) : MainClass(className)
{
}
void SubClass::doSomething()
{
printf("Called from SubClass\n");
}
Call:
int main()
{
MainClass M1("test");
SubClass sub("SubClass");
MainClass *pointer = ⊂
M1.doSomething(); //Outputs 'Called from MainClass'.
sub.doSomething(); //Outputs 'Called from SubClass'.
pointer->doSomething(); //Also outputs 'Called from SubClass', since it points to sub and because sub overrides the behaviour from MainClass.
}
To call the parent method from the child method, you need to invoke the method from within the override with the parent class.
Example (in SubClass::doSomething): MainClass::doSomething().

How can I implement a vector<class> template's function?

I want to implement a template like this,
class animal{
}
class beast : public animal {
public:
beast(string name){}
void cry(){
cout<<"kuuuuu"<<endl;
}
}
int main(){
vector<animal*> a;
a.push_back(beast("tiger"))
vector[0].cry();
}
I want to implement similar to it. But my visualstudio cannot find the cry() function.
Please, how can I do it?
animal does not have a cry method. So you cannot call a cry on animal.
Also you have numerous syntax errors, which should give you errors before this line:
Your vector contains pointers and you are trying to stuff object itself inside.
To access member of object pointer points to, you should use ->, not ..
A lot of changes needed.static_cast is essential to call your cry method.
class definition should end with ;
Since you created vector<animal*>, you need to new the object before push back.
When you invoke the function cry , you need to static_cast it back to beast* and use -> instead . to invoke the cry function.
class animal{
};
class beast : public animal {
public:
beast(std::string name){}
void cry(){
std::cout<<"kuuuuu"<<std::endl;
}
};
int main(){
std::vector<animal*> a;
a.push_back(new beast("tiger"));
(static_cast<beast*>(a[0]))->cry();
}
#include <vector>
#include <iostream>
#include <string>
using namespace std;
class animal {
public:
virtual void cry() = 0; // declare public virtual cry method
};
class beast : public animal {
public:
beast(string name) {
}
void cry() {
cout << "kuuuuu" << endl;
}
};
int main() {
vector<animal*> a;
a.push_back(new beast("tiger")); // create new object and end with semicolon
a[0]->cry(); // use -> instead of . to call cry method of beast object pointed at
}

returning a different type than polymorphic function defined

The problem I'm having is with a polymorphic class: the animal class has a function "virtual animal* get() = 0;" which is defined in the dog class as "dog* get() { speak2(); return this; }".
I've read somewhere a while ago that changing the return type this way is legal but it doesn't seem to work as I expected: when the get function is called it prints the expected value but when I try to assign the return value to the dog class pointer I get a invalid conversion error, and when I try to call the speak2() function it says that it has no such member.
What I'm looking for is to be able to call something along the lines of "barn.front()->get()->speak2();". Is there any way to achieve something similar to this without any dynamic_casts or any such casts?
I've named the classes in a logical manner so its easy to read and also added some notes in the form of comments throughout the following code:
#include <iostream>
#include <vector>
using namespace std;
class animal
{
public:
virtual ~animal() {}
virtual void speak1() = 0;
virtual animal* get() = 0;
};
class dog : public animal
{
public:
void speak1() { cout << "print-speak1!"; }
void speak2() { cout << "print-speak2!"; }
dog* get() { speak2(); return this; }
};
int main()
{
vector<animal*> barn;
barn.push_back(new dog());
barn.front()->speak1(); // prints "print-speak1!"
barn.front()->get(); // prints "print-speak2!"
barn.front()->get()->speak2();
// error: 'class animal' has no member named 'speak2'
// but then why does "barn.front()->get();" print "print-speak2!"?
dog* dogptr = barn.front()->get();
// error: invalid conversion from 'animal*' to 'dog*' [-fpermissive]
dogptr->speak2();
// for the sake of -Werror=unused-variable
for(vector<animal*>::iterator i = barn.begin(); i != barn.end(); ++i)
{
delete *i;
}
barn.clear();
return 0;
}
There are two things going on with your code at different times. First, the compiler sees the return type of barn.front() as animal*. No matter what you do. Calling member speak2() on type animal* always fails.
Your member get() is a virtual function, and with line barn.front()->get(); is invoked using a virtual dispatch. This means that the function that gets called is only known at runtime, based on what is the real (so-called dynamic) type of the animal. That way you can modify what the behaviour of get() is for each animal.
Differing return value of get() does not matter here. The type checking that compiler does is (obviously) done at compile time, and thus against animal::get(). The covariant return type is only useful if you do a direct call to an object of static type dog.
In your case, a hackish way would be to cast the type to dog, something like
static_cast<dog*>(barn.front())->speak2();
Of course you will burn if the actual type of the barn.front() is not a dog. And by that I mean undefined behaviour - the program may crash, throw exception or silently continue with corrupted data.
More correct approach in my oppinion would be to separate different actions into a generic interface, like:
class animal
{
public:
virtual ~animal() {}
virtual void makeSound() = 0;
};
class dog : public animal
{
public:
void bark() { cout << "hoof"; }
void makeSound() { bark(); }
};
class cat : public animal
{
public:
void meow() { cout << "meow"; }
void makeSound() { meow(); }
};
int main()
{
vector<animal*> barn;
barn.push_back(new dog());
barn.push_back(new cat());
barn.front()->makeSound();
barn[1]->makeSound();
}
The whole point of programming to interfaces is to use the interface class as the access point and rely on the implemented concrete types to conform to the interface. For you this means that you should access the actual animals in your vector via the pointer to animal. If you define speak2() as a pure virtual function within the animal class and use the animal* instead of dog*, your program will run. The question remains if all animals will have speak2() ability, but that's the issue of the design. Notice that I have placed the using directive below the class implementation, since it is not a good practice to have using namespace directives within library code.
Here's the code with changes:
#include <iostream>
#include <vector>
class animal
{
public:
virtual ~animal() {}
virtual void speak1() = 0;
virtual void speak2() = 0;
virtual animal* get() = 0;
};
class dog : public animal
{
public:
void speak1() { std::cout << "print-speak1!" << std::endl; }
void speak2() { std::cout << "print-speak2!" << std::endl; }
dog* get() { speak2(); return this; }
};
using namespace std;
int main()
{
vector<animal*> barn;
barn.push_back(new dog());
barn.front()->speak1(); // prints "print-speak1!"
barn.front()->get(); // prints "print-speak2!"
barn.front()->get()->speak2();
// error: 'class animal' has no member named 'speak2'
// but then why does "barn.front()->get();" print "print-speak2!"?
animal* dogptr = barn.front()->get();
// error: invalid conversion from 'animal*' to 'dog*' [-fpermissive]
dogptr->speak2();
// for the sake of -Werror=unused-variable
for(vector<animal*>::iterator i = barn.begin(); i != barn.end(); ++i)
{
delete *i;
}
barn.clear();
return 0;
}
When you use barn->front()->get(), you have access to a animal* pointer. Speak2() is not defined for animal, thus the no member error.
Given
class animal
{
public:
virtual animal * get () = 0;
};
class dog : animal
{
public:
virtual dog * get () {...}
};
Then,
// Compiler sees call to "dog::get()".
dog * d = new dog();
d->get();
// Compiler sees call to "animal::get()", which may return
// an instance of any type derived from "animal".
animal * a = d;
d->get();

Checking for derived class type

This is an example of a problem I have while designing an interface.
I have a class Animal and I have derived Cat, Dog and Lion from it. Now I have a function 'feedFood' which takes in the base class Animal as parameter. Based on the type of animal I should feed different food to the Animal.
So how do I check the type of the animal in the 'feedFood' function.
There are 3 methods I could think of
Adding a 'AnimalType' enum in the base class which is set to the right type in the derived class.
Add a virtual function in base class to return a string with animal type. In derived class return the proper string for the animal name.
Use typeid or dynamic_cast to check the type of the derived class in the 'feedFood' function.
Which is the best method or is there any other better approach for this?
You are currently saying this:
void feedFood(Animal &);
Cat myCat;
Dog myDog;
feedFood(myCat);
feedFood(myDog);
// Problem: How does feedFood() know what's going on?
To use polymorphism, make the feeding function a virtual member of Animal:
struct Animal
{
virtual void feedFood() = 0; // pure virtual or default behaviour, up to you
virtual ~Animal() { } // always provide virtual destructor!
/* ... */
};
struct Cat : public Animal
{
void feedFood() { /* Cat implementation */ }
/* ... */
};
// Usage:
// via reference
void feed(Animal & a) { a.feedFood(); }
// via pointer
Animal * b = new Bat;
b->feedFood();
Try this:
class Animal{};
class Dog: public Animal{};
class Cat: public Animal{};
class Lion: public Animal{};
void FeedFood(Dog& d)
{
cout << "Feeding the dog.\n";
return;
}
void FeedFood(Cat& c)
{
cout << "Feeding the cat.\n";
return;
}
void FeedFood(Lion& l)
{
cout << "Feeding the lion.\n";
}
void FeedFood(Animal& a)
{
cout << "Feeding an unknown animal.\n";
return;
}
With the above functions, the compiler will take care of feeding animals.
Sometimes, functionality may be better placed outside the class.
Okay, somewhat complicated, but resolves at compile time:
template <class _Derived>
class Animal
{};
class Dog: public Animal<Dog>
{
public:
void Feed()
{
cout<<"Feeding Dog...";
}
};
class Cat: public Animal<Cat>
{
public:
void Feed() { /* Feed Cat*/ }
};
And implement ONE template function:
template<class _AnimalType>
void FeedAnimal(_AnimalType& animal)
{
animal.Feed();
}
Create instance of any class, and call FeedAnimal:
Dog dog;
Cat cat;
FeedAnimal(dog);
FeedAnimal(cat);
If Feed is not implemented by derived-class, you may not get error, until you call Feed template function. Therefore, if Lion is implemented like:
class Lion : public Animal<Lion>
{};
You won't get any error that Feed is missing from class. As soon as you make call to FeedAnimal with Lion, you would get error that Lion is missing Feed method.
This is one of the hack to ensure that derived class implements Feed:
template <class _Derived>
class Animal
{
void (_Derived::*pDummy)();
public:
Animal()
{
pDummy = &_Derived::Feed;
}
};
Dirty, but works!
Not the animal gets food feeded, but it ates it. So add a virtual 'eat' method together with some FoodProvider on which the Animal can eat on.
Update:
So instead of an
void feed (const Food & food);
use
virtual void eatFrom (FoodProvider * provider);
That way you can also implement different food resources in your provider.

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