Polymorphic Enums - c++

Polymorphic Enums?
In C++, we often use polymorphism to allow old code to handle new
code--for instance, as long as we subclass the interface expected by a
function, we can pass in the new class and expect it to work correctly
with the code that was written before the new class ever existed.
Unfortunately, with enums, you can't really do this, even though there
are occasional times you'd like to. (For instance, if you were
managing the settings for your program and you stored all of them as
enum values, then it might be nice to have an enum, settings_t, from
which all of your other enums inherited so that you could store every
new enum in the settings list. Note that since the list contains
values of different types, you can't use templates.)
If you need this kind of behavior, you're forced to store the enums as
integers and then retrieve them using typecasts to assign the
particular value to the setting of interest. And you won't even get
the benefit of dynamic_cast to help you ensure that the cast is
safe--you'll have to rely on the fact that incorrect values cannot be
stored in the list.
I'm quoting from a C++ programming tutorial.
Can anybody please explain more deeply and with some examples how Polymorphic Enums work?
And in the case I have templates?

Simply stated, an enum is simply a named constant value, for instance:
enum Settings
{
setting_number_0,
setting_number_1,
setting_number_2,
};
In the above example, setting_number_X is simply a named constant for the value X, as enumeration values start at 0 and increase monotonically.
Keeping these then, in some type of container gives a basic storage type of integers, but can still be somewhat typesafe.
std::vector<Setting> app_settings;
// this works
app_settings.push_back(setting_number_0);
// this is a compile time failure, even though the underlying storage
// type for Setting is an integral value. This keeps you from adding
// invalid settings types to your container (like 13 here)
app_settings.push_back(13);
// but you also cannot (directly) add valid setting values (like 1)
// as an integral, this is also a compile time failure.
app_settings.push_back(1);
Now, suppose you wanted to add additional specific setting types and keep them all in a container.
enum DisplaySettings
{
// ...
};
enum EngineSettings
{
// ...
};
Now, if you wanted to keep all the settings in a single container, you cannot safely. You could store all the integral values in a container of std::vector<int> or similar, but that breaks down in that you cannot determine what integral types belong to what setting enumerations. Also, since the types are different you cannot store them in a single type-safe container.
The correct way to go about this is would be to store the functionality of the setting in the container, something like this:
#include <vector>
#include <iostream>
// This is our "base class" type so we can store lots of
// different setting types in our container
class setting_action
{
public:
// we enable the setting by calling our function
void enable_setting()
{
setting_function_(this);
}
protected:
// This is a function pointer, and we're using it to get some
// compile time polymorphism
typedef void (*setting_function_type)(setting_action* setting);
// these can only be constructed by derived types, and the derived
// type will provide the polymorhpic behavior by means of the
// above function pointer and based on the derived type's handler
setting_action(setting_function_type func)
: setting_function_(func)
{
}
public:
~setting_action()
{
}
private:
setting_function_type setting_function_;
};
// This is the derived type, and where most of the magic
// happens. This is templated on our actual setting type
// that we define below
template <class Setting>
class templated_setting_action
: public setting_action
{
public:
templated_setting_action(Setting setting)
: setting_action(&templated_setting_action::enable_setting)
, setting_(setting)
{
}
// This function catches the "enable_setting" call from
// our base class, and directs it to the handler functor
// object that we've defined
static void enable_setting(setting_action* base)
{
templated_setting_action<Setting>* local_this =
static_cast<templated_setting_action<Setting>*>(base);
local_this->setting_();
}
private:
Setting setting_;
};
// this is just a shorthand way of creating the specialized types
template <class T>
setting_action* create_specialized_setting_action(T type)
{
return
new templated_setting_action<T>(type);
}
// Our actual settings:
// this one displays the user name
struct display_user_name
{
void operator()()
{
std::cout << "Chad.\n";
}
};
// this one displays a short welcome message
struct display_welcome_message
{
void operator()()
{
std::cout << "Ahh, the magic of templates. Welcome!\n";
}
};
// now, we can have one container for ALL our application settings
std::vector<setting_action*> app_settings;
int main()
{
// now we can add our settings to the container...
app_settings.push_back(create_specialized_setting_action(display_user_name()));
app_settings.push_back(create_specialized_setting_action(display_welcome_message()));
// and individually enable them
app_settings[0]->enable_setting();
app_settings[1]->enable_setting();
// also, need to delete each setting to avoid leaking the memory
// left as an exercise for the reader :)
return 0;
}

Related

Keeping track of member arguments of derived class

Let's say I have a library with a virtual class called INode. The user of the library is suposed to use INode for creation of multiple concrete nodes (e.g. single ConcreteNode) with any kind of functionality specialized by the user.
Right now, if inside of any ConcreteNode I want to declare a "special" scalar argument, I call arguments.scalar.add(0) method, witch creates me a new entry inside an intern vector of scalar values (is it practically std::vector<double>) and initiates it with an id = 0. Besides the named vector of doubles called scalar I also prepared containers with vectors (arguments.vector.) and matrices (argument.matrix.) to be called in the same way as shown.
All of this is motivated with the thought, that I want to keep track of the state (e.g. bool is_set;) for all arguments of ConcreteNode. This must happen "internally", such that the creator of ConcreteNode does not need to keep track of these arguments manually via creation of such state variables.
My current approach works, but it is limited to predefined containers (scalar, vector, matrix). Is the library used wanted to use some other data type, he must add a new entry inside INodeclass. Second issue is, that if I create ConcreteNode witch is only using a single scalar argument, containers for vectors and matrices are also created. This leads to dead code, unnecessary memory usage and the most important part is that I am making requests on all containers like bool arguments.are_set(); witch checks through all of the arguments, even if there are none of them created for vector and matrix.
I am searching for a better solution. One thought was, what if I will overload new operator inside INode class, such that every newly created argument of any type inside derived class is internally registered in the way that is it is given few state arguments and few standard functions set/get.
Then the code might be way flexible and probably look like this:
struct ConcreteNode : INode
{
ConcreteNode() { bool* arg = new bool; }
void foo() override { /* ... use arg ... */ };
}
On this point I ask myself if this boilerplate with new is really necessary. Couldn't I just create a wrapper around the new operator to make it look like normal member initialization like bool arg;. Or maybe I am missing some clever trick in cpp witch allows me keep track of created members directly.
I hope I did the point of my thoughts clear and you could help me to go further with them.
EDIT1: Also I was thinking about making some template structures witch might behave like.
struct ConcreteNode : INode
{
ConcreteNode()
{ arguments.add<bool>("arg");
arguments.set<bool>("arg") = true; }
void foo() override { /* ... bool b = arguments.get<bool>("arg"); ... */ };
}
EDIT2: Right now, for the current state of code I declare new arguments inside derived class like this:
struct ConcreteNode : INode
{
ConcreteNode(double a, std::vector<double> b)
{ arguments.add.scalar(0);
arguments.add.vector(1);
arguments.set.scalar(0) = a;
arguments.set.vector(1) = b;
}
void foo() override
{
double c = arguments.get.scalar(0);
std::vector<double> d = arguments.get.vector(1);
// ...
};
}

How do i get the value inside a multiple type vector (without adding the <type>)?

I created a vector that stores any type of value (int, bool, string, &, object,...). I can store stuff, but i have no idea how to get an specific element ([index]). EDIT: (without adding the type)
I haven't tried many things because i have no clue. The only tecnic i can think of is dynamic_cast, but since is a template makes no sense.
#include <vector>
#include <iostream>
struct slot {
virtual void print() = 0;
};
template<typename kind>
struct item : public slot {
kind value;
item(kind value) : value{ value } {};
void print()override { std::cout << value<<std::endl; }
};
class Bag {
std::vector<slot*> backpack;
public:
template<typename kind>
void append(kind stuff) {
backpack.push_back(new item<kind>(stuff));
}
void print_to_test() {
for (slot* it : backpack) { it->print(); }
}
//kind get()...How do i get an item value?
};
Bag bag;
bag.append(1);
bag.append(true);
bag.append("Hola");
bag.append(1232131);
void* a = nullptr;
bag.append(a);
bag.print_to_test();
//works fine, prints everything
//but can't get an specific value, like bag[index]
The dynamic cast will work. Note that it requires at least one virtual method - a destructor can be used if nothing else.
Yes, there isn't a way how can you reliably retrieve the value. C++ doesn't have a general object base as other languages nor any useful runtime reflection.
What you've implemented is known as type erasure and is actually used in e.g. std::function or std::any.
You should not use raw pointers and new for ownership. Use std::unique_ptr instead. Also since you only refer to the objects through the base class you need the virtual destructor. Otherwise, you won't be able to delete them correctly, again one more reason for std::unique_ptr as it deletes the pointer by itself.
If you want to get the value, what would you do with it? To quote Bjarne Stroustrup:
There is no useful universal class: a truly universal carries no semantics of its own.
Yes, you can store this value in std::any, but that's it, what would you want to do with it? Print it? Well, in that case it's no longer any but printable as in your example, so either use templates or virtual methods to express these traits in the types of the stored objects.
Consider using std::variant for known set of possible types and prefer std::any to owning void*. If you need the latter rethink your design choices first.
As others pointed out, dynamic_cast will work fine (as long as the caller knows what type is in the specific index) :
item<int>& someInt = dynamic_cast<item<int>&>(*bag.backpack[0]);
std::cout << "someInt: ";
someInt.print();
Note: You didn't provide accessor to backpack member, so I assumed it's public
Output:
someInt: 1

Accept and identify any type of input C++

I'm trying to write a simple C++ program that creates a linked list. I would like to make this list be able to store any type of data in its container. However, I realised that my main problem is being able to accept any type of input and storing it. For example, if the variable std::cin stores to is of type string, only strings will be accepted, and this variable must be defined before program compilation.
My question is: is there any way to accept any type of input with a std::cin (or any other input method) and then call certain functions depending on the input's type?
Something along the logic of...
cin >> data
if (data.type == string)
{
cout << "data's type: string"
}
if (data.type == int)
{
cout << "data's type: int"
}
Thank you!
C++ is (mostly) statically typed. That is, the types of variables have to be known at compile time and cannot change at runtime, e.g. depending on some user input.
The one exception to this rule are polymorphic classes: When you have a base class with some virtual member function, then there will be a way (most likely a pointer as a member of all instances of that class) to distinguish between sub classes of that class (and itself):
struct Base {
virtual ~Base() {}
};
struct SubA : public Base {};
struct SubB : public Base {};
// ...
Base const & instance = SubA{};
try {
SubA const & as_subA = dynamic_cast<SubA const &>(instance);
// The instance is a SubA, so the code following here will be run.
} catch (std::bad_cast const &) { /* handle that somehow */ }
Using this mechanism, or preferably the virtual function itself, you can have different behavior depending on the dynamic type of an instance, which is only known at run time.
C++ being a flexible language, you can - of course - also implement something similar on your own:
struct Thing {
enum class Type {
Integer, String, Vector
} type;
union {
int integer;
std::string string;
std::vector<int> vector;
} data;
// Plus a lot of work in constructors, destructor and assignment, see rule of 5
};
Using something like this allows you to have objects with a "type" of dynamic nature, and are able to do different things depending on what type the object actually has at run time.
But of course you don't need to write that on your own (though its not that hard), there are a lot of implementations like for example boost::any and boost::variant.

How to create user defined type template class object C++

I am struggling with allowing user to select data type template will be created as.
Since template type must be defined on compile, I must specify data type template will use eg(string,int, so on), but that means I cannot change it latter on, from lets say string to int even if my template supports it, because template class object was declared as string.
My class declaration below:
template <class T>
class MyHashTable
{
public:
string deleted="deleted";
unsigned short tableSize;
// array of vectors, hash table container
vector<T>* myTable;
vector<T>* deletionTable;
MyHashTable(unsigned short tableSize) : myTable(new vector<T>[tableSize]), deletionTable(new vector<T>[tableSize])
{
this->tableSize=tableSize;
}
object declaration outside class
MyHashTable <string>* myChainedTable=NULL ;
string tableType;
object initialization
if (myChainedTable)
{
delete myChainedTable;
myChainedTable=NULL;
}
getType();
if (!myChainedTable)
{
if (tableType=="string")
myChainedTable= new MyHashTable<string>(length);
if (tableType=="char")
MyHashTable<char> myChainedTable(length); // no difference with or without using new keyword
if (tableType=="double")
MyHashTable<double> myChainedTable(length);
if (tableType=="float")
MyHashTable<float> myChainedTable(length);
if (tableType=="int")
MyHashTable<int> myChainedTable(length);
cout<<tableType<<" table of size "<< length<<" created"<<endl;
I attempted passing class object to functions instead of having it as global variable, but couldnt get it work either.
What I really need is single template object that can have: int,string,char,double,float types, I have 3 functions that need to have access to template class object, and having 5 different objects and 200 lines of if statements for each situation sounds like worst possible solution.
I been stuck on this for a while and just cant figure out how to do it and any help will be appreciated.
void getType()
{
cout<<"Enter table type, types available: int, char, float, double, string.\n";
tableType=getInput();
while((tableType != "int")&&(tableType !="float")&&(tableType !="double")&&(tableType!="char")&&(tableType !="string"))
{
cout<<"Invalid type, please try again "<<endl;;
tableType=getInput();
}
}
Your question is at the boarder between templates and variants.
The template is compile time. So you have to choose at compile time the type you want for your object. Your conditional approach can't work (see comments to question).
On the other side, you seem to need a dynamic choice of type at runtime.
If you want to go on on template way: (edit based on comments)
You'd need to have all the templates inherit from a single polymorphic base class (one common interface with virtual functions). Example:
class MyHashBase // common base class for all templates
{
public:
virtual void addElement(void *ptrelem) = 0; // adding an element must be implemented by template. With void* since future template type unknown from base class
virtual void displayAll() = 0;
};
The templates would need then implement the virtual functions:
template <class T>
class MyHashTable : public MyHashBase
{
public:
unsigned short tableSize;
vector<T>* myTable; // I leave it as it is, but you could implement these as vector<T> instead of vector<T>*
vector<T>* deletionTable;
MyHashTable(unsigned short tableSize) : myTable(new vector<T>[tableSize]), deletionTable(new vector<T>[tableSize]), tableSize(tableSize)
{ }
void addElement(void* ptrelem)
{ myTable->push_back(*reinterpret_cast<T*>(ptrelem)); } // reinterpret the void* of the common interface as a T*
void displayAll()
{ copy(myTable->begin(), myTable->end(), ostream_iterator<T>(cout, "\n")); }
};
You could then have your myChainedTable be a pointer to the common base type, and intialise this pointer in the way you did with the string case (i.e. using new).
MyHashBase *myChainedTable = nullptr;
//...
if (tableType == "string")
myChainedTable = new MyHashTable<string>(length);
else if (tableType == "double")
myChainedTable = new MyHashTable<double>(length);
//...
You could then use the common API, for example if tableType is "double":
double d1 = 3.1415, d2 = 1.4142;
myChainedTable->addElement(&d1); // ATTENTION: you must ensure to provide pointer to the correct data type
myChainedTable->addElement(&d2);
myChainedTable->displayAll();
You'll certainly have a coupe of if required in the calling code, but you could reduce them to minimum by carefully designing the base class (for example, you could add a virtual clone function, to duplicate the data without need to know the type by the caller).
However, using a single signature for the common functions of the base class is cumbersome. To make the virtualisation possible you need to pass parameters through void* pointer which is not so nice and rather error prone.
Alternate way with variants
You could also use boost variants which are meant for managing objects with dynamic definition of types.
In this case you would not need template for your own data structure. You would create a MyHashTable with elements of type boost::variant< int, std::string, ... >.
You could then access to the right value of the object if you know its type (as in your myChainedTable) by using: boost::get<int> (element) (or boost::get<string>(), ...).
If you don't know the type on an element you could use the concept of "visitor" to chose automatically the appropriate function to exectue depending on the type.
Edit: alternate way with unions:
If you're not allowed to use variants another alternative could be use a union. I don't know the topic of you rassignment, but you have the choice whether you use a union to define the elements (like the variants, without templates) or to use a template type as you did, but define myChainedTable to be a union of pointers to the different template instantiations. But yes, it requires a lot of ifs...
Templates are resolved at compile time. Your container type is resolved at runtime. Templates are clearly not the solution here. The first thing that comes to my mind is a combination of boost::any and std::vector instead.

Dynamic mapping of enum value (int) to type

It appeared that this problem is quite common in our job.
We we are sending an int or enum value through the network, then we receive it we would like to create/call a particular object/function.
The most simply solution would be to use the switch statement, like below:
switch (value) {
case FANCY_TYPE_VALUE: return new FancyType();
}
It works fine, but we would have plenty of these switch blocks, and when we create new value and type, we would need to change all of them. It does seem right.
Other possibility would be to use the templates. But we cannot, since the value of enum is defined in runtime.
Is there any right design pattern for that, or any right approach?
It seems like a very general and common problem in every day coding...
Try a map:
struct Base { };
struct Der1 : Base { static Base * create() { return new Der1; } };
struct Der2 : Base { static Base * create() { return new Der2; } };
struct Der3 : Base { static Base * create() { return new Der3; } };
std::map<int, Base * (*)()> creators;
creators[12] = &Der1::create;
creators[29] = &Der2::create;
creators[85] = &Der3::create;
Base * p = creators[get_id_from_network()]();
(This is of course really crude; at the very least you'd have error checking, and a per-class self-registration scheme so you can't forget to register a class.)
You can actually do this with some template trickery:
#include <map>
template <typename Enum, typename Base>
class EnumFactory {
public:
static Base* create(Enum e) {
typename std::map<Enum,EnumFactory<Enum,Base>*>::const_iterator const it = lookup().find(e);
if (it == lookup().end())
return 0;
return it->second->create();
}
protected:
static std::map<Enum,EnumFactory<Enum,Base>*>& lookup() {
static std::map<Enum,EnumFactory<Enum,Base>*> l;
return l;
}
private:
virtual Base* create() = 0;
};
template <typename Enum, typename Base, typename Der>
class EnumFactoryImpl : public EnumFactory<Enum,Base> {
public:
EnumFactoryImpl(Enum key)
: position(this->lookup().insert(std::make_pair<Enum,EnumFactory<Enum,Base>*>(key,this)).first) {
}
~EnumFactoryImpl() {
this->lookup().erase(position);
}
private:
virtual Base* create() {
return new Der();
}
typename std::map<Enum,EnumFactory<Enum,Base>*>::iterator position;
};
This allows you to create a new derived object from a given enum, by saying
// will create a new `FancyType` object if `value` evaluates to `FANCY_TYPE_VALUE` at runtime
EnumFactory<MyEnum,MyBase>::create(value)
However, you have to have some EnumFactoryImpl objects, which could be static in some function or namespace.
namespace {
EnumFactoryImpl<MyEnum,MyBase,Derived1> const fi1(ENUM_VALUE_1);
EnumFactoryImpl<MyEnum,MyBase,Derived2> const fi2(ENUM_VALUE_2);
EnumFactoryImpl<MyEnum,MyBase,Derived3> const fi3(ENUM_VALUE_3);
EnumFactoryImpl<MyEnum,MyBase,FancyType> const fi1(FANCY_TYPE_VALUE); // your example
}
These lines are the single point where your source code maps enum values to derived types. So you have everything at the same location, and no redundancy (this eliminates the problem of forgetting to change it in some places, when adding new derived types).
One option is to maintain a dictionary of creators(which has the same interface) that can create a concrete type. Now the creation code will search in the dictionary for an int value (resulting from the enum sent from the client) and call the create method, which returns the concrete object via a base-class pointer.
The dictionary can be initialized at one place with the concrete creators corresponding to each possible enum values.
The problem here is that you have to extend this dictionary initialization code when you add a new type of object. A way to avoid is as following.
Let the creator look for a singleton factory instance and register itself in the constructor with the type enums(integers) with which it can create a concret object.
Create a DLL for one/set of creators and have a global instance of the creators.
The name of the DLL can be entered in a config file which is read by the factory in the initialization. The factory loads all the DLLs in this file and this results in the creation of the static objects which registers themselves with the factory.
Now the factory has the map of all the type enums which it can create with the concrete object creators.
The same object creator look-up mechanism is implemented to create the objects.
Now, the factory doesn't need to be extended at all since step 3,4 and 5 doesn't change for new objects introduced. Step 1 can be implemented in one place.
Only thing you need to do is to add a global object for each of the new concrete type which should be there since the C++ doesn't support reflection natively.
kogut, I don't propose this as an answer, but since you ask me to expand on my comment on your original question here's a very brief summary of what the .net environment gives you...
public enum MyEnum
{
[MyAttribute(typeof(ClassNone))]
None,
[MyAttribute(typeof(ClassOne))]
One,
[MyAttribute(typeof(ClassTwo))]
Two,
[MyAttribute(typeof(ClassThree))]
Three
}
So you have your basic enum One, Two, Three etc. which works just like....er....an enum!
But you also code up a class called MyAttribute (and in fact for more information in this area, just search for Attributes). But as you can see this allows you to say, at design time, that such-and-such an enum value is associated with such-and-such a class.
This information is stored in the enum's metadata (the value of a managed environment!) and can be interrogated at runtime (using Reflection). Needless to say this is very powerful, I've used this mechanism to systematically strip out loads of maps of the kind proposed in other answers to your question.
An example of the usefulness is this...at one client I worked with, the convention was to store statuses as strings in a database on the grounds that they would be more readable to a human who needed to run a table query. But this made no sense in the applications, where statuses were pushed through as enums. Take the above approach (with a string rather than a type) and this transform happened on a single line of code as data was read and written. Plus, of course, once you've defined MyAttribute it can be tagged onto any enum you like.
My language if choice these days is c# but this would also be good in (managed) c++.