I am working on a code generation tool with which I can generate Data classes and associated Manipulator classes specific to each Data class. As part of the generation tool, some common, non-generated files are provided to perform various functionality, including accessing the manipulator classes. The user is expected to interact with the Data classes and the common files, but is not expected to interact directly with the Manipulator classes.
I recently added the ability to generate derived classes to the tool. Things work out really well until trying to access a derived class manipulator from a base class reference. A VERY stripped down example of what I am trying to do is here (comments in the code are addressed in my question below):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
#include <string>
#include <iostream>
// Content similar to that found in generated Data classes
class BaseManip;
class BaseData
{
public:
typedef BaseManip ManipType; // Can this be made virtual?
virtual ~BaseData() = default;
};
class DerivedManip;
class DerivedData: public BaseData
{
public:
typedef DerivedManip ManipType; // I want this type picked up from a
// BaseData* to an obj of this class.
};
// Content similar to that found in generated Manipulator classes
class BaseManip
{
public:
void doIt(const BaseData& data)
{
std::cout << "doIt Base Class" << std::endl;
doItImpl_Base_extensions(data);
}
protected:
virtual void doItImpl_Base_extensions(const BaseData& data) {}
};
class DerivedManip : public BaseManip
{
protected:
virtual void doItImpl_Base_extensions(const BaseData& data)
{
const DerivedData& myData = dynamic_cast<const DerivedData&>(data);
std::cout << "doIt Derived Class" << std::endl;
}
};
// Content similar to that found in generated
// library code provided by generation tool;
template <typename TYPE>
void masterDoIt(TYPE& data)
{
// Here I want to create a DerivedManip object when a BaseData& to a
// DerivedData object is passed into this function.
typename TYPE::ManipType manip;
manip.doIt(data);
}
// User code
int main()
{
DerivedData data;
std::cout << "Derived masterDoIt" << std::endl;
masterDoIt(data);
std::cout << std::endl;
std::cout << "Base masterDoIt" << std::endl;
BaseData& baseRef = data;
masterDoIt(baseRef);
std::cout << std::endl;
}
| |
When masterDoIt is called with a BaseData& argument, masterDoIt uses the ManipType from BaseData rather than the ManipType from DerivedData, even though the object is truly of type DerivedData.
I know that I could provide a virtual getManipObject function of some sort rather than the typedef, but I was wondering, is there were a way to make the typedef "virtual" so that masterDoIt will create the correct Manipulator when a BaseData& to a DerivedData object is passed in?
Note, the project is currently using a C++11 compiler.
Edit: simplified code for Manip classes.