Declaring a dynamic data type in C ++

I want to be able to do the following:

I have an array of strings containing data types:

string DataTypeValues[20] = {"char", "unsigned char", "short", "int"}; 

Then later I would like to create a variable of one of the data types at runtime. I will not know at compile time what the correct data type should be.

So, for example, if at runtime I defined a variable x, which should be of type int:

 DataTypeValues[3] x = 100; 

Obviously this will not work, so how can I do something like this?

+10
c ++
source share
13 answers

The simple answer is that you cannot - types must be known at compile time in C ++. You can do something like this using boost :: any or union, but it will not.

+16
source share

you will need to use unions to achieve something similar, but handling joins is a very difficult question, so you have to choose a container class that wraps the join logic behind the interface, like Boost.Variant or Qts QVariant

+12
source share

You can not. Such run-time metaprogramming is not supported in C ++.

+3
source share

Anyone who says they can't do this in C ++ is missing one obvious solution. Here you can use the base class, you need to define the commonly used interface there, and then all the derived classes will be any types that you need. Put it in a smart pointer, suitable for the container, and there you go. You may need to use dynamic type output if you cannot put enough interface into the base class, which always frowned because it is ugly, but it is there for some reason. And dynamically distributing your types is probably not the most efficient thing, but, as always, it depends on what you use it for.

+2
source share

The only thing you can do is manually iterate over the types and compare each of them. You can also use the factory object here, but it will be associated with a bunch.

+1
source share

I think you are really looking for a dynamically typed language. Insert an interpreter if you must stick with C ++!

Or you can implement something similar to the component model using interfaces for working with wrapped data. Start with the space base class - IObject, then implement the interfaces for IInteger, IDouble, IString, etc. Then the objects themselves are created using the factory.

Or you could just use void buffers with factory ... This is a century-old way to avoid static typing in C / C ++ (without using inheritance-based polymorphism). Then sprinkle with a generous amount of reinterpret_cast.

+1
source share

The Visual Basic data type β€œVariant” is what you are talking about. It can contain everything, primary data types, arrays, objects, etc.

"The Collection class in OLE Automation can store elements of different data types. Since the data type of these elements cannot be known at compile time, methods for adding elements to elements from collection use cases and retrieving from them. If Visual uses a basic construct" For each ", the iterator variable must be an object or variant type." - from http://en.wikipedia.org/wiki/Variant_type

The page above gives some insight into how options are used, and shows how OLE is used in C ++ to work with options.

+1
source share

The closest you can get is with templates:

 template<int i> class Data { }; template<> class Data<0> { typedef char type; } template<> class Data<1> { typedef unsigned char type; } template<> class Data<2 { typedef short type; } template<> class Data<3> { typedef int type; } Data<3>::Type x; 

If you need something more complex, Boost has a C ++ bridge - Python.

+1
source share

In your simple example, it will be of little use in that you do not just use the widest type in the list as a universal container and, if necessary, impose smaller types (or even rely on implicit drops).

You can get detailed information about unions, classes, polymorphism, RTTI, Boost options, etc., but just for a list of different integers of width is hardly worth the effort.

It seems to me that you have a perceived problem for which you invented an impractical solution that you are now asking for help. You will probably be much better off describing your original problem rather than solving the problem.

+1
source share

Also, do not forget that all the functions that should work on this mysterious data type. Most functions are designed to use only one type, such as adding. Functions are overloaded to handle additional types.

How do you know at runtime what type of variable?

+1
source share

The only way that comes to mind now is to use the old C style, which used a pointer to void:

 void *unkown; 

Leter, you can assign any object to it, as shown below:

 unkown = (void *)new int(4); 

If you know the type at run time, you can run the specified function for such a variable, as shown below:

 if(type==0) { // int printf("%d\n", * ((int*)unkown) ); } else { // other type } 

This method (casting void *) is used, for example, when the malloc function [etc.] is used.

I am not saying that it is good practice when C ++ is now much more developed. Still agree with people saying that this is not the best solution to your problem. But perhaps after some redesign you may find this useful.

You can also find an interesting auto-type with C ++ 11. http://en.cppreference.com/w/cpp/language/auto

0
source share

I think this answer will be a few years later. But for people who could view this stream, a possible solution to this would be to use template variables. For example:

 template<typename T> T var; template<typename T> T arr[10]; int main() { int temp; var<int> = 2; cout << var<int> << ' '; // this would output 2 var<char> = 'a'; cout << var<int> << ' '; // var<int> value would be a space character cout << var<char> << ' '; // this would output 'a' for(int i = 0; i < 10; i++) { switch(i % 2) { case 0: arr<int>[i] = ++temp; break; case 1: arr<char>[i] = 'a' + ++temp; break; } cout << endl; for(int i = 0; i < 10; i++) { switch(i % 2) { case 0: cout << arr<int>[i] << ' '; break; case 1: cout << arr<char>[i] << ' '; break; } } return 0; } 

The only problem with this is that you will need to find out the type of the variable of what is currently in the variable (for example, storing an integer in an array, that the variable is "id" (the identifier you gave it) for a specific type ) If you do not know or do not know what is inside a specific variable or array location, I do not suggest using this.

0
source share

use union and create your own dynamic class. pseudo code such as:

 union all{ char c; unsigned char uc; short s; int i; }; class dynamic{ public: char Type; all x; template <class T> dynamic(char type_,T y){ int Int; char Char; unsigned char Uchar; short Short; if(typeof(y) ==typeof(Char)){ Type=1; }else if(typeof(y) ==typeof(Uchar)) { Type=2; }else if(typeof(y) ==typeof(Short)) { Type 3; }else{ Type=4; } switch (Type) { case 1: xc=y; break; case 2: x.uc=y; break; case 3: xs=y; break ; case 4: xi=y; break ; } } auto get() { switch(Type) { case 1: return xc; case 2: return x.uc; case 3: return xs; case 4: retuen xi; } } //make also the operators function you like } ; 

however, you should avoid using a dynamic type as much as possible because it is inefficient
(in this example, each dynamic object will occupy 5 bytes)



it will also slow down your code (a bit).
if in your example you want to use the dynamic type of a numeric variable only to reduce memory usage, you should forget about the dynamic and just use an integer as a type (where an integer can contain all char, unsigned char and short characters at once).

but if you want to use it because you need a dynamic type between something really different (for example, between int and a string or a custom object), then this will be one of your options.

0
source share

All Articles