# creating a dynamic variable type

## Recommended Posts

I am wanting to create an object that is basically a object that can store any type of variable(int, string, user created, etc...) by doing something like:
variable* a_string = new variable("string", "data");
variable* a_int = new variable("int", 4);


now the trouble i am having is storing the data. Now i know i can use template for a class/function when the passed variable might be anything but is there a way to do that for a variable?

##### Share on other sites
well... I've made a property class before.

Basically without having type checks you can simply do it like this:

// we need a destructor function for each typetypedef void (*Dtor)(void*); // this generates a simple destructor for any template typetemplate <class T>void Destructor (void* p){	delete (T*) p;} // Our property holderclass Property{private:	// pointer to the object	void* data;	// function ptr to its destructor	Dtor dtor; public:	// constructor	Property () : data (0), dtor (0) { }	// destructor	~Property ()	{		// destroy if object is present		if (data)			dtor (data);	} 	// set the property (destroy existing if present)	template <class T>	void Set (T* object)	{		if (data)			dtor (data);		data = object;		dtor = &Destructor<T>;	} 	// get the property	template <class T>	T& Get (void)	{		return *(T*) data;	}}; // test it outint main (){	Property p;	p.Set (new int (123));	if (p.Get<int>() == 123) {		printf ("It works!!!!");	}	p.Set (new std::string ("Hello, world!"));	if (p.Get<std::string>() == "Hello, world!") {		printf ("It still works!!!!");	}}

This is a very quick version of a variable type. You'd need proper checks and whatnot.

##### Share on other sites
Agreed, though ur own version doesnt involve 20mb of headers.

[forgive me if you only need a few headers for variant - ive tried using boost and its waaaaaaaayyyyy too big]

##### Share on other sites
Quote:
 Original post by thre3deeAgreed, though ur own version doesnt involve 20mb of headers.[forgive me if you only need a few headers for variant - ive tried using boost and its waaaaaaaayyyyy too big]

The reason for that is that the Boost version covers all the cases, such as containers, copying, type-safety, and more.

Stuff like:
p.Set (new int (123));	if (p.Get<std::string>() == "123") {		printf ("What happens here?");	}        std::vector<Property> properties; // will either leak memory or crash

Variant type is also not optimal, there's boost::any, or, if you want a light-weight version, cdiggins::any.

The advantage of any types is that all variables smaller or equal to sizeof(void*) will be allocated in place, thereby not trashing the heap or cause extra dereference on access.

##### Share on other sites
Oh, yes. It definitely depends on your intentions for it. Diggins' version is a good solution if you're planning on using something like this in a tight loop. Variant also requires one to specify the types you plan on it holding, so it wouldn't be comfortable if they plan on stuffing anything and everything in there.

Still, no matter which you go with, something like Boost or Diggins' implementation would be best. Boost is very well made and will introduce heaps of safe functionality that would otherwise take years to (re)implement. Also, you'd have to include every single header in the Boost library to get 20MiB — you typically wouldn't go that far unless you're actually using everything in there. Variant or Any alone are only going to add ~10KiB.

##### Share on other sites
Please I after i say this I really don't want to here people telling me don't to do this because i frankly don't care if people think this is a waste of time, I don't think it is and it is something the is very interesting to me. The reason for this functionality is for my custom scripting language i am building.

The only reason I am timid about using the Boost library is because i have been told it was not that great and not to use it. Now this must have been over a year ago so I am sure a lot has changed. I also do not remember if i was told not to use it because it license what not free enough(I would like to be able to release my code under whatever license i want without having to release any of my source code except for and modification I make to the boost library) or if the code was not the best in speed. How is Boost speed wise? From what i see it seem like license would allow for me to use the code it any licensed project, is that right?

##### Share on other sites
Quote:
 Original post by 3dmodelerguyNow this must have been over a year ago so I am sure a lot has changed.

Nothing has changed in one year. Where exactly did boost turn out to be a bottle-neck for you? What did you use as alternative?

Quote:
 I also do not remember if i was told not to use it because it license what not free enough(I would like to be able to release my code under whatever license i want without having to release any of my source code except for and modification I make to the boost library)

Boost license is permissive to open source or commercial projects. It's the only reason it's even usable, anything less wouldn't make it viable.

Quote:
 From what i see it seem like license would allow for me to use the code it any licensed project, is that right?

Yes.

Quote:
 or if the code was not the best in speed. How is Boost speed wise?

It did Kessel run in 12 parsecs. It's fast enough for you, young man. :)

What are your performance requirements? If you looked at the link I provided about cdiggins any version, it explains nicely why it exists.

All libraries explain the performance implications of the design decisions made. In some cases, it matters, in others, it doesn't.

Notable examples include function and signal libraries, which, for sake of reliability and portability allocate more memory as is usually necessary, as well as perform dynamic allocations.

Same "problem" exists with boost::any, which is why I suggested a light-weight alternative, which covers what you want to do completely (std::pair<std::string, any>, for example).

Keep in mind that such hacks are surprisingly complex, and have many hidden pitfalls. The existing ::any implementations have been tested well enough to be shown to work.

##### Share on other sites
Quote:
 Original post by 3dmodelerguyThe only reason I am timid about using the Boost library is because i have been told it was not that great and not to use it.

I'd like to find whoever told you that and smack him/her upside the head. [smile]

IMO the boost smart pointer classes are about as important as std::string.

##### Share on other sites
If you're on Windows why not get the VARIANT type a chance? or _variant_t (wrapper for it in MFC) ?

Boost is always good but indeed can be scary at first:)

##### Share on other sites
Well I am going to ask my friend what he reason was against using Boost, I my not have remember correctly, I will let you know what his answer is.

##### Share on other sites
Quote:
 Original post by valentin-galeaIf you're on Windows why not get the VARIANT type a chance? or _variant_t (wrapper for it in MFC) ?Boost is always good but indeed can be scary at first:)

I want this scripting language to be cross platform and rather not but anything built off of Microsoft built stuff.

##### Share on other sites
and what about simplest solution union ? [smile]

union any_type
{
int integer;
unsigned char byte;
char string[32];
struct color { unsigned char a, b, g, r; };

// etc...
};

any_type my_color;
my_color.color.r = 255;

##### Share on other sites
From what i read, I can not use union on user created objects like std::string, is this not correct?

##### Share on other sites
unions cannot contain anything with a constructor. This includes std::string.

##### Share on other sites
But you can use char[] or you can create simple replacment of std::string like
class str
{
public:
char* my_string;
...

};

union any_type
{
...
str stringdata;
};
Then you can set my_value.stringdata = "something";

##### Share on other sites
I guess it's not the simplest solution any more.

##### Share on other sites
Quote:
 Original post by SiCraneunions cannot contain anything with a constructor. This includes std::string.

but unions can have constructors.

I wrote you small example. It is not perfect, no error checking, but it solves your solution.
// string definition, no constructor :)class String{	char *data;public:	void setNull() { data = 0;}	char* operator=(char* t)	{		int size = strlen(t);		data = new char[ size ];		strcpy(data, t);		return data;	}};// unionunion my_data{        // union can have ctor	my_data()	{               // call fake constructor		str.setNull();	}	int integer;	String str;};my_data dt;dt.str = "hello";printf("%s\n",dt.str);dt.integer = 1;printf("%d\n", dt.integer);

gives you result:
hello
1

hope this helps

##### Share on other sites
Well my friend says he think boost it fine just a bit bloated for his taste. I think I will try the void* and static_cast and see how far I get.

##### Share on other sites
Quote:
 Original post by streamerhope this helps

The whole point of a stringy class is to encapsulate and automate the memory management and conversion concerns (and other goodies) — things that require constructors and destructors to work well. What good is there in reimplementing something with less functionality, less safety, and less maturity?

If cross platform is truly a concern, maturity is a good thing. It means time to test it under many hardware and software configurations, which may bring about strange bugs that, without a level of understanding of the system involved comparable to the original designers of the components, you're not going to be able to predict.

I'm won't speak ill of making a language, I admit I enjoy tinkering in it myself. Yet I also realize that it's a waste of time from a productivity standpoint. Unless it's some super-specialized language that does but one thing for your game that no other language can do (hard to imagine nowadays though), you're better off just embedding an already well-established general scripting system. If cross platform and generalized scripting are goals, just use something like Boost and Boost.Python. It took all of five minutes to install and have a basic example running under Ubuntu. And you get the years of effort and dedication that the Python community has put into it to make it a viable system.

I'm assuming you're trying to making a game. If all you're interested in is making a language, by all means go for it. Though, just as a bit of friendly caution, it's probably going to be a long and boring road for you. If you're really serious about it, I'd read through the dragon book. Very helpful in such things. I only have the first edition, which is admittedly a bit dated, but it still sits proudly on my easy-reach bookcase.

##### Share on other sites
That example leaks. It also requires the user (of the code) to be aware of the contents of the union, such that they have to make sure they assign the right types to the right variables.

This sort of defeats the idea of an easy to use any-data type.

##### Share on other sites
Quote:
 I wrote you small example. It is not perfect, no error checking, but it solves your solution.

It actually doesn't -- your 'solution' contains an non-trivial operator=. An object of a class with a non-trivial default or copy constructor, a non-trivial destructor, or a non-trivial assignment operator cannot be a union member.

##### Share on other sites
Quote:
 Original post by tychonThat example leaks. It also requires the user (of the code) to be aware of the contents of the union, such that they have to make sure they assign the right types to the right variables.This sort of defeats the idea of an easy to use any-data type.

Yes I know. As I said it isn't perfect. It just shows my opinion on this question.
Assigning right values to union isn't so hard to do,
enum TYPE { eSTRING, eINT, etc... };

struct custom_value
{
TYPE typeOfVariable;
union my_data ....
};

##### Share on other sites
Quote:
Original post by jpetrie
Quote:
 I wrote you small example. It is not perfect, no error checking, but it solves your solution.

It actually doesn't -- your 'solution' contains an non-trivial operator=. An object of a class with a non-trivial default or copy constructor, a non-trivial destructor, or a non-trivial assignment operator cannot be a union member.

Actually I made this in VS 2005, compiled, runned and worked.

##### Share on other sites
That's nice. Doesn't make it correct, or a good idea. See section 9.5 of the standard.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628360
• Total Posts
2982261

• 10
• 9
• 13
• 24
• 11