Reputation: 16185
I am trying to write some generic code:
int _pID = _plant->getPlantInternalID();
std::string _plantName = getPlantBasedUponInternalID(_pID);
_plantName
returns a string of the plant, like Broccoli
but is there a way to do something like this:
for (int f=0; f < _f.getPlants().size(); f++)
{
std::shared_ptr<Plant> sbas = _f.getPlants().at(f);
std::shared_ptr<_plantName> sder2 = std::dynamic_pointer_cast<_plantName>(sbas);
}
notice I am putting in _plantName
but really I need to do something like:
std::shared_ptr<Broccoli> sder2 = std::dynamic_pointer_cast<Broccoli>(sbas);
what is needing to do something like this called and how do I accomplish it?
UPDATE: I am just getting the ID based upon an internal ID I made up:
std::string HUDForStatus::getPlantBasedUponInternalID(int _id)
{
switch (_id)
{
case 114: // Asparagus
return ASPARAGUS::plantName.c_str();
break;
case 113: // Beets
return BEETS::plantName.c_str();
break;
case 115: // Bok Choy
return BOKCHOY::plantName.c_str();
break;
case 107: // Broccoli
return BROCCOLI::plantName.c_str();
break;
case 101: // Carrot
return CARROT::plantName.c_str();
break;
case 110: // Celery
return CELERY::plantName.c_str();
break;
case 103: // Corn
return CORN::plantName.c_str();
break;
case 116: // Eggplant
return EGGPLANT::plantName.c_str();
break;
case 102: // Green Beans
return GREENBEANS::plantName.c_str();
break;
... <snip>...
}
}
Upvotes: 0
Views: 199
Reputation: 64223
c++ is statically typed language, and it is not possible to create variables of some random type at run-time. You could do it if your classes have a common interface, as shown in the example at the end.
To get a unique name of a type at run-time is easy with typeid.
#include <iostream>
#include <string>
#include <typeinfo>
#include <memory>
struct B
{
virtual ~B(){}
virtual void foo() = 0;
};
struct A1 : B
{
virtual void foo()
{
std::cout << 1 << std::endl;
}
};
struct A2 : B
{
virtual void foo()
{
std::cout << 2 << std::endl;
}
};
std::unique_ptr<B> getFooCaller( const std::string v )
{
if ( v==typeid(A1()).name() )
{
return std::unique_ptr<B>(new A1);
}
else if ( v==typeid(A2()).name() )
{
return std::unique_ptr<B>(new A2);
}
return 0;
}
int main(int argc, char* argv[])
{
if (argc!=2)
{
std::cout << "pass type name" << std::endl;
}
auto b = getFooCaller(argv[1]);
if (b)
{
b->foo();
}
else
{
std::cout << "expecting " << typeid(A2()).name() <<" or " << typeid(A2()).name() << std::endl;
}
}
Upvotes: 0
Reputation: 29724
std::shared_ptr<T> std::dynamic_pointer_cast<std::shared_ptr<U>& sp >
can only work when
dynamic_cast<T*>(sp.get())
would work. So in your case
std::shared_ptr<_plantName> sder2 = std::dynamic_pointer_cast<_plantName>(sbas);
conversion Plant*
to std::string
should be valid through dynamic_cast
. For this to happen, std::string
should be derived from Plant, and this means also that these types should be polymorphic (for this some virtual function is needed), because the dynamic_cast
operator uses the runtime type information generated from polymorphic classes. But it is not possible.
solution:
1.
derive your classes from Plant
- then conversion like
std::shared_ptr<Broccoli> sder2 = std::dynamic_pointer_cast<Broccoli>(sbas);
will be possible. this might be of help.
2 . use abstract interface which Plant
will implement. Then you will use methods from this interface to do dynamic type identification at runtime
Upvotes: 0
Reputation: 96251
This is not the C++ way to solve the problem. Instead, give Plant
an appropriate abstract interface and then you don't NEED to know which concrete type you're working with. Instead you just use the interface and let the virtual dispatch decide which plant it is and which implementation to call.
Upvotes: 3