I have a universal data type, which is passed by value, but does not maintain the type information. We store only pointers and basic data types(like int, float etc) inside this. Now for the first time, we need to store std::string inside this. So we decided to convert it into std::string* and store it. Then comes the problem of destruction. We don't like to copy the std::string every time. So i am thinking of an approach like this. Say the data type looks like this
class Atom
{
public :
enum flags
{
IS_STRING,
IS_EMPTY,
HAS_GOT_COPIED,
MARKER
};
private:
void* m_value;
std::bitset<MARKER> m_flags;
public:
.....
Atom( Atom& atm )
{
atm.m_flags.set( HAS_GOT_COPIED );
.....
}
.....
~Atom()
{
if( m_flags.test(IS_STRING) && !m_flags.test(HAS_GOT_COPIED) )
{
std::string* val = static_cast<std::string*>(m_value);
delete val;
}
}
};
Is this a good approach to find out whether there is no more reference to std::string*? Any comments..
I have looked at boost::any and poco::DynamicAny. Since i need serialization, i can't use those.
Thanks,
Gokul.
One major flaw with this approach is that you really need a reference count, not a single bit "has been copied" flag. The bit won't work if you copy the string multiple times. As written, you will get into trouble if you create a copy of an Atom and delete the copy before the original:
Atom a("hello world");
if (...) {
Atom b(a);
// b is destroyed, deleting the string
}
// Uh oh, the string's been deleted but a is still referencing it.
cout << (string) a;
I would not re-invent the wheel. If boost::any doesn't work out of the box you could still use it internally in place of your m_value field to store the data for your Atom class. That would take care of all the construction/copying/destruction details for you.
I think you should look into the possibility of using boost::shared_ptr (or std::tr1::shared_ptr).
You might want to feed "copy on write" into google and read up on the topic. How it is usually implemented, what it is used for, and what its drawbacks are.
And have you looked at boost::any?
One of my first tasks at my first job was to design a variant class. You can find some basic code (and discussion) here in this comp.lang.c++.moderated post.
Since you also need serialization, you might be interested in the JsonCpp library. I think it offers just what you are looking for: a datatype that can be a string, bool, int, array, object, etc... (the Json::Value class.)
Aside from whether this kind of 'universal data type' is a good idea, if you're not copying the string, can this class be sure that it owns the string it has pointer to? Can you guarantee that only strings allocated via new will be passed in to the class to take ownership?
The design of this class looks as though it will be problematic.
Related
I'm studying C++ and in all my "experiments" i'm trying to understand temporary objects (rvalues) lifetime.
My question is:
Having an object which contains a const char* pointer, what happens when i want to use a constructor which takes "const char*" as argument? Usually temporary objects get destructed automatically but what happens with pointers created in this way?
I'm not using std::string or other c++11 classes for now because I'm just focusing on understanding rvalueness.
An example below:
class MyAwesomeClass {
private:
const char* data;
public:
MyAwesomeClass(const char* ptr) {
this->data = ptr;
}
MyAwesomeClass(MyAwesomeClass&& myAwesomeClassRVALUE) {
this->data = myAwesomeClassRVALUE.data;
myAwesomeClassRVALUE.data = nullptr;
}
~MyAwesomeClass() {
delete data;
}
};
int main() {
MyAwesomeClass s = "My Awesome Class' string data.";
return 0;
}
Usually temporary objects get destructed automatically but what happens with pointers created in this way?
Pointers are objects themselves. Same thing happens to temporary pointer objects as happens to all other temporary objects.
Your example deletes a pointer pointing to a string literal, so the behaviour of the program is undefined. The class would also have a broken assignement operators even if it was used correctly by passing pointer to an array allocated with new[].
As for rvalueness, the only rvalue expression in the example that I could find is nullptr.
Note this answer is based on a previous edit of the question where MyAwesomeClass was a String class.
Your String class is not really a string class as it doesn't own the underlying string data. It's more akin to std::string_view.
You have two avenues I can see you can pursue:
Your class owns the underlying data. In this case the class is a wrapper around std::string and has std::stringdata member. Look up composition. No need to worry about lifetime asstd::string` is well behaved.
Your class is like a "pointer/reference/view" to another string. In this case you have a const char* and maybe std::size_t size data member. You basically have a std::string_view (except for the wisdom, expertise and experience that went into designing std::string_view). Since you don't own the underlying data you can't do anything about the lifetime of the underlying data. The user of the class must make sure it doesn't end with a "YourStringView" to an expired object, just as he/she needs to make sure it doesn't end up with a reference/pointer to an expired object.
The semantics of these two scenarios are wildly different (as the difference between an object and a pointer to an object).
Anyway I wouldn't recommend you do any of this except for maybe learning reasons. std::string_view already exists so just use that. If you want the printing capabilities use the fmt library or the C++ format library (that is based on the mentioned fmt library).
Even if you decide to do this for learning purposes I highly encourage you look into these alternatives and learn from how they are doing things.
MyAwesomeClass(const char* ptr)
{
this->data = ptr;
}
~MyAwesomeClass()
{
delete data;
}
Oh no, no, no! No!!
Please look into RAII and rule of 0/3/5. Your class either owns the pointed object or it doesn't. If it owns it then it is responsible for creating it and deleting it. If it doesn't then it can't do either. You can't have "half of responsibilities" where you are responsible for deleting it but not for creating it.
In user code you should never need to manually manage memory. Use the rule of 0.
Quick answer is that your class does not own the data, but just the raw pointer. Under certain conditions you will see a problem with delete operator. Raw pointer are not great tool to ensure correct object ownership.
Is there a compromise between managing memory and easy/idiomatic programming in C++?
For example, let's say I have the following classes. We have an Item that someone may purchase, and a ShoppingList of those Items. Let's just say Item and ShoppingList are big data structures with more features than shown and that we would not want to pass them by value normally (but they are stripped down to the basics features in this example).
class Item {
private:
std::string name;
float cost;
public:
Item(std::string name, float cost) : name{name}, cost{cost} { }
std::string toString(void) {
return name + " = " + std::to_string(cost);
}
~Item() { std::cout << "~Item()" << std::endl; }
};
class ShoppingList {
private:
std::vector<Item *> items;
public:
ShoppingList() {}
void addItem(Item &item) {
items.push_back(&item);
}
std::vector<Item *> getItems() {
return items;
}
~ShoppingList() {
std::cout << "~ShoppingList()" << std::endl;
}
};
Now, I want to be able to conveniently do something like the following (inline the argument).
ShoppingList shoppingList{};
shoppingList.add(Item{"soap", 1.99}); // no
C++17 will not me allow to try this either.
ShoppingList shoppingList{};
shoppingList.add(&Item{"soap", 1.99}); // no
shoppingList.add(new Item{"soap", 1.99}); // no
Instead, I have to do something like this.
ShoppingList shoppingList{};
Item soap{"soap", 1.99};
shoppingList.add(soap);
The above is "ok" for adding 1 element, but things get "worse" when I try to use a for loop. The item created on each loop ends with the same address and I do not end up with the intended effect.
ShoppingList shoppingList{};
auto products = std::vector<std::string>{"brush", "comb"};
for (auto product : products) {
Item item{product, 0.99};
shoppingList.addItem(item);
}
It seems unreasonable, to me, to do the following.
ShoppingList shoppingList{};
Item item1{"item1", 0.99};
Item item2{"item2", 0.99};
Item item3{"item3", 0.99};
// and so on
shoppingList.addItem(item1);
shoppingList.addItem(item2);
shoppingList.addItem(item3);
// and so on
There's just so many ways of thinking about how to make it easier to use the code. One way would be to use raw pointers. So I may change the method signature of ShoppingList.addItem(...) to as follows.
void addItem(Item *item);
Then I can do some less difficult use of the objects as follows.
ShoppingList shoppingList{};
shoppingList.addItem(new Item{"item1", 0.99});
shoppingList.addItem(new Item{"item2", 0.99});
shoppingList.addItem(new Item{"item3", 0.99});
With this new method signature, for loops should work.
ShoppingList shoppingList{};
auto products = std::vector<std::string>{"brush", "comb"};
for (auto product : products) {
shoppingList.addItem(new Item{product, 0.99});
}
Ok, so this approach makes it easier to use/write the code, but valgrind analysis says Leak_DefintelyLost where I start using new.
Another approach is smart pointers. So let's wrap the objects into smart pointers; in particular shared_pointer. Here's the new ShoppingList using smart pointers.
class ShoppingList {
private:
std::vector<std::shared_ptr<Item>> items;
public:
ShoppingList() {}
void addItem(std::shared_ptr<Item> item) {
items.push_back(item);
}
std::vector<std::shared_ptr<Item>> getItems() {
return items;
}
~ShoppingList() {
std::cout << "~ShoppingList()" << std::endl;
}
};
Usage will look like the following.
ShoppingList shoppingList{};
shoppingList.addItem(std::make_shared<Item>("soap", 32.0));
shoppingList.addItem(std::make_shared<Item>("shampoo", 32.0));
valgrind does not detect a single memory leak issue.
The only problem I have with using shared_ptr is verbosity and nested types. This declaration looks bad to me. That is a lot of : and < with >.
std::vector<std::shared_ptr<Item>> items;
In one situation where I had a map of maps of big data structures, I considered using shared pointers and ended up with a declaration as follows. If another coder looks at what the intention is (or if I myself come back later to troubleshoot), what is the intention here?
std::map<std::string, std::map<std::string, std::vector<std::shared_ptr<SomeClass>>>> dataBag;
It seems to me that the : and < and > are polluting the code and intent all for the purpose of managing memory leaks. I am not sure what's good or bad or idiomatic to write C++17 while being concise but also preventing memory leaks boostrapped by the language constructs.
Now, I did encounter the idea of RAII. But mocking some classes with that approach (raw pointers only), valgrind still shows Leak_DefinitelyLost.
Any general guidance on I suppose what I would refer to as idiomatic C++ that is memory leakage sensitive/preventative would be helpful. I was going to go down the road of creating factories to store all the pointers that I will create across my API, but I realized that approach would cause the memory to continue to build up even when there are no longer references to some pointers (and smart pointers already handle that part).
At this point, I am almost resigned to the acceptance of living with smart pointers (though there may be diamond and colon operators all over the place) to avoid memory leaks.
One way or another, if you want a collection of items, you're going to have to create each item in the collection. Storing pointers to items mostly helps if they're really so tremendously huge that copying them is unacceptable, even if it happens only a few times, such as when a vector reallocates its memory.
As for passing by reference: right now, you're defining the parameter as an lvalue reference. That means the reference can only refer to an lvalue. Thus the requirement to create a named object (an lvalue) then pass it.
You apparently don't want that. In your case, you have a couple of choices. One is a reference to const. Unlike a (non-const) lvalue reference, this can bind to a temporary object.
Another choice would be to use an rvalue reference. An rvalue reference has the advantage that it can bind to an rvalue (such as a temporary object), and also that it's "aware" that it's dealing with an rvalue, so it can "steal" the contents of that object. This is particularly useful if the object mostly contains a pointer to the actual data, in which case you can just copy the pointer (and modify the existing object so it won't destroy the data when it's destroyed).
In most cases, you're best off starting with the simplest code that could work. Create the vector of objects, and live with the fact that they'll get copied. Sometime later, if you find that you have a real bottleneck from copying those objects as that vector is reallocated, it's soon enough to change your code--such as to store std::unique_ptrs instead of storing objects directly. But that's not your first choice. Chances are pretty good that when you profile the code, you'll find that copying those objects isn't a bottleneck at all, so putting work into keeping them from being copied would have been wasted.
A long time ago I get c++ advice.
Never use raw pointers.
As soon as you are not low-level library developer. You don't need raw pointers. Don't need. Period.
I would like to know if there are any problems with the construction <type>*&& in C++. Let me give a concrete example.
Say we have a class that should be constructed from an array. We would usually do something like this:
class Things
{
public:
Things(const ThingType* arrayOfThings, int sizeOfArray)
: myArray(new ThingType[sizeOfArray])
{
for (int i = 0; i < sizeOfArray; i++)
myArray[i] = arrayOfThings[i];
}
private:
ThingType* myArray;
}
This is fine if we want to preserve arrayOfThings, because we are doing a deep copy of it. Moreover, by using const we are ensuring it won't be modified inside the constructor.
But suppose our program has a lot of statements like this one:
Things myThings(new ThingType[9001] {thing_0, ... , thing_9000}, 9001);
This might seem weird, but it may happen that the huge ThingType array is returned from a function as a rvalue.
In that case, we don't care about preserving the pointer passed as a parameter. In fact, we definitely don't want to do a deep copy of it, because it would be a huge waste of time preserving something we are about to destroy anyways.
One possible solution to this would to add another constructor that would handle the case of a non-const rvalue ThingType pointer, like a general move constructor handles the case of a non-const rvalue instance of the class:
public:
Things(ThingType*&& arrayOfThings, int sizeOfArray)
: myArray(arrayOfThings)
{
arrayOfThings = NULL;
}
This seems to be solving the problem for me, but I did not find much information about the <type>*&& construction seen above. Is it kosher, or will I be sent to the dungeons for mixing pointers and references?
After some time I believe I found satisfactory - although far from optimal - solutions. Since no one answered the question, I will share the best workarounds I found.
As Justin pointed out, using ThingType*&& can lead to trouble when we take the address of a variable of ThingType (but not of a ThingType pointer, as he implied in his answer) in the constructor call.
If t is a ThingType, the expression &t is an r-value of type ThingType*, so Thing myThing(&t, ...) will call the move constructor, with the result of making myThing.myArray point to t. This is not what we would want in most cases.
One solution is to use vectors instead of arrays, as illustrated below:
// Copy
explicit Things(const std::vector<ThingType>& vectorOfThings)
: myVector(vectorOfThings)
{ }
// Move
explicit Things(std::vector<ThingType>&& vectorOfThings)
: myVector(std::move(vectorOfThings))
{ }
The move constructor would then be used in situations like this:
Things myThings(vector<ThingType>{thing_0, ... , thing_9000});
Although this solves the problem, it is not feasible if we are dependent on an API which returns raw pointers, or if we want don't want to give up arrays. In this case, we can use smart pointers to solve the problem.
Suppose, we have a function ThingType* generateArray() which we want to use to initialize our object of type Things. The first thing we should do is to wrap this function with another function that returns a smart pointer instead.
unique_ptr<ThingType[]> generateSmartPointer()
{
return unique_ptr<ThingType[]>(generateArray());
}
Here I used a unique_pointer, but this could change depending on the implementation.
Now we add a new constructor to Things, with a instance of unique_ptr as an argument. This will act as the move constructor for arrays of ThingType:
Things(unique_ptr<ThingType[]> thingsPointer, int sizeOfArray)
: myArray(thingsInput.release()), size(sizeOfArray)
{ }
unique_ptr<T>.release() is used to get the array, and at the same time make the unique pointer release ownership of it, preventing the array from being deleted once the unique pointer is destroyed.
And that's it. These are the two best solutions I found to this problem, and while they are far from perfect, they have worked so far considering the objectives for each implementation.
First off: I searched half the web to find an answer with this as a solution that came closest. It is, however, too heavyweight for me though so I am looking a little less complex.
Well then, some context: I am building a system which should be able to process incoming messages from a queue and then store the outcome of these messages in another queue. I would like to store these responses in a generic class because I am storing it in a multimap.
The response class currently is defined as follows
class COutboundMsg
{
public:
enum eTypeHint {
thNone,
thSomeType,
thLast
};
eTypeHint m_TypeHint;
void* m_OutboundData;
COutboundMsg(COutboundMsg::eTypeHint TypeHint, void* data);
};
COutboundMsg::COutboundMsg(COutboundMsg::eTypeHint TypeHint, void* data) :
m_TypeHint(TypeHint),
m_OutboundData(data)
{
}
Now, the current way of working would involve a user to do something like this:
CSomeType* data = new CSomeType();
COutboundMsg(COutboundMsg::thSomeType , (void*) data);
It would be up to the user at the other end to cast the void* back to CSomeType* (using the type hint) and delete it.
It don't like it.
I'd rather have the m_OutboundData contained in an auto_ptr or something and make sure that it deletes itself when done.
Any ideas? Maybe a different approach altogether
Normally polymorphism is used for a system like this; any item that can be put in the Outbound queue derives from QueueItem and the queue contains QueueItem* or a smart pointer to a QueueItem.
Since the items all derive from a common base, you can safely delete the QueueItem* or allow a smart pointer to handle it. This approach also allows you to use dynamic_cast to make sure that the pointer is, in fact, pointing to an object of the type you think it is.
If this approach is possible, be sure to make the QueueItem destructor virtual, otherwise the derived class's destructor won't be called.
shared_ptr stores a deleter to use to delete the object, and so does not depend on the static type of the pointer at the time of deletion. So something like this should do the right thing:
COutboundMsg(eTypeHint TypeHint, shared_ptr<void> msg);
shared_ptr<CSomeType> data(new CSomeType);
COutboundMsg(COutboundMsg::thSomeType, data);
If the set of messages is known before hand (transmit/receive), rather than polymorphism, consider a variant type, I'm taking specifically about boost::variant<>.
The advantage of this approach is that each message is a specific type (I know it seems like you don't want to implement this - however as a long term design feature, I think you'll find this approach extensible) and the variant describes the set of messages, let me show a quick example:
let's say I have two messages
struct Logon{};
struct Logout{};
I define a variant to hold the possible set of messages, at a given time it's only ever one of them..
typedef boost::variant<Logon, Logout> message_type;
Now I can store this in any container, and pass it around like normal, the only difference is that the truly generic way to access them is via visitors, e.g.
struct process : boost::static_visitor<>
{
void operator()(Logon const& cLogon)
{
// do stuff
}
void operator()(Logout const& cLogout)
{
// do stuff
}
};
// method that processes a given message
void processMessage(message_type const& cMsg)
{
// don't know what this message is, that's fine, hand it to the visitor
boost::apply_visitor(process(), cMsg); // the correct overload will be called for the message
}
...I think it's slightly better than void* ;)
I need to store a list of various properties of an object. Property consists of a name and data, which can be of any datatype.
I know I can make a class "Property", and extend it with different PropertySubClasses which only differ with the datatype they are storing, but it does not feel right.
class Property
{
Property(std::string name);
virtual ~Property();
std::string m_name;
};
class PropertyBoolean : Property
{
PropertyBoolean(std::string name, bool data);
bool m_data;
};
class PropertyFloat : Property
{
PropertyFloat(std::string name, float data);
float m_data;
};
class PropertyVector : Property
{
PropertyVector(std::string name, std::vector<float> data);
std::vector<float> m_data;
};
Now I can store all kinds of properties in a
std::vector<Property*>
and to get the data, I can cast the object to the subclass. Or I can make a pure virtual function to do something with the data inside the function without the need of casting.
Anyways, this does not feel right to create these different kind of subclasses which only differ by the data type they are storing. Is there any other convenient way to achieve similar behavior?
I do not have access to Boost.
C++ is a multi-paradigm language. It shines brightest and is most powerful where paradigms are mixed.
class Property
{
public:
Property(const std::string& name) //note: we don't lightly copy strings in C++
: m_name(name) {}
virtual ~Property() {}
private:
std::string m_name;
};
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const std::string& name, const T& data)
: Property(name), m_data(data);
private:
T m_data;
};
typedef std::vector< std::shared_ptr<Property> > property_list_type;
Edit: Why using std::shared_ptr<Property> instead of Property*?
Consider this code:
void f()
{
std::vector<Property*> my_property_list;
for(unsigned int u=0; u<10; ++u)
my_property_list.push_back(new Property(u));
use_property_list(my_property_list);
for(std::vector<Property*>::iterator it=my_property_list.begin();
it!=my_property_list.end(); ++it)
delete *it;
}
That for loop there attempts to cleanup, deleting all the properties in the vector, just before it goes out of scope and takes all the pointers with it.
Now, while this might seem fine for a novice, if you're an only mildly experienced C++ developer, that code should raise alarm bells as soon as you look at it.
The problem is that the call to use_property_list() might throw an exception. If so, the function f() will be left right away. In order to properly cleanup, the destructors for all automatic objects created in f() will be called. That is, my_property_list will be properly destroyed. std::vector's destructor will then nicely cleanup the data it holds. However, it holds pointers, and how should std::vector know whether these pointers are the last ones referencing their objects?
Since it doesn't know, it won't delete the objects, it will only destroy the pointers when it destroys its content, leaving you with objects on the heap that you don't have any pointers to anymore. This is what's called a "leak".
In order to avoid that, you would need to catch all exceptions, clean up the properties, and the rethrow the exception. But then, ten years from now, someone has to add a new feature to the 10MLoC application this has grown to, and, being in a hurry, adds code which leaves that function prematurely when some condition holds. The code is tested and it works and doesn't crash - only the server it's part of now leaks a few bytes an hour, making it crash due to being out of memory about once a week. Finding that makes for many hours of fine debugging.
Bottom line: Never manage resources manually, always wrap them in objects of a class designed to handle exactly one instance of such a resource. For dynamically allocated objects, those handles are called "smart pointer", and the most used one is shared_ptr.
A lower-level way is to use a union
class Property
union {
int int_data;
bool bool_data;
std::cstring* string_data;
};
enum { INT_PROP, BOOL_PROP, STRING_PROP } data_type;
// ... more smarts ...
};
Dunno why your other solution doesn't feel right, so I don't know if this way would feel better to you.
EDIT: Some more code to give an example of usage.
Property car = collection_of_properties.head();
if (car.data_type == Property::INT_PROP) {
printf("The integer property is %d\n", car.int_data);
} // etc.
I'd probably put that sort of logic into a method of the class where possible. You'd also have members such as this constructor to keep the data and type field in sync:
Property::Property(bool value) {
bool_data = value;
data_type = BOOL_PROP;
}
I suggest boost::variant or boost::any. [Related question]
Write a template class Property<T> that derives from Property with a data member of type T
Another possible solution is to write a intermediate class managing the pointers to Property classes:
class Bla {
private:
Property* mp
public:
explicit Bla(Property* p) : mp(p) { }
~Bla() { delete p; }
// The standard copy constructor
// and assignment operator
// aren't sufficient in this case:
// They would only copy the
// pointer mp (shallow copy)
Bla(const Bla* b) : mp(b.mp->clone()) { }
Bla& operator = (Bla b) { // copy'n'swap trick
swap(b);
return *this;
}
void swap(Bla& b) {
using std::swap; // #include <algorithm>
swap(mp, b.mp);
}
Property* operator -> () const {
return mp;
}
Property& operator * () const {
return *mp;
}
};
You have to add a virtual clone method to your classes returning a pointer to a newly created copy of itself:
class StringProperty : public Property {
// ...
public:
// ...
virtual Property* clone() { return new StringProperty(*this); }
// ...
};
Then you'll be able to do this:
std::vector<Bla> v;
v.push_back(Bla(new StringProperty("Name", "Jon Doe")));
// ...
std::vector<Bla>::const_iterator i = v.begin();
(*i)->some_virtual_method();
Leaving the scope of v means that all Blas will be destroyed freeing automatically the pointers they're holding. Due to its overloaded dereferencing and indirection operator the class Bla behaves like an ordinary pointer. In the last line *i returns a reference to a Bla object and using -> means the same as if it was a pointer to a Property object.
A possible drawback of this approach is that you always get a heap operation (a new and a delete) if the intermediate objects must be copied around. This happens for example if you exceed the vector's capacity and all intermediate objects must be copied to a new piece of memory.
In the new standard (i.e. c++0x) you'll be able to use the unique_ptr template: It
can be used inside the standard containers (in contrast to the auto_ptr which must not be used in the standard containers),
offers the usually faster move semantics (it can easily passed around) and
takes care over the held pointers (it frees them automatically).
I see that there are lots of shots at trying to solve your problem by now, but I have a feeling that you're looking in the wrong end - why do you actually want to do this in the first place? Is there some interesting functionality in the base class that you have omitted to specify?
The fact that you'd be forced to switch on a property type id to do what you want with a specific instance is a code smell, especially when the subclasses have absolutely nothing in common via the base class other than a name (which is the type id in this case).
Starting with C++ 17 we have something called as std::variant and std::any.
std::variant
An instance of std::variant at any given time either holds a value of one of its alternative types, or in the case of error - no value.
std::any
The class any describes a type-safe container for single values of any copy constructible type.
An object of class any stores an instance of any type that satisfies the constructor requirements or is empty, and this is referred to as the state of the class any object. The stored instance is called the contained object. Two states are equivalent if they are either both empty or if both are not empty and if the contained objects are equivalent.
The non-member any_cast functions provide type-safe access to the contained object.
You can probably do this with the Boost library, or you could create a class with a type code and a void pointer to the data, but it would mean giving up some of the type safety of C++. In other words, if you have a property "foo", whose value is an integer, and give it a string value instead, the compiler will not find the error for you.
I would recommend revisiting your design, and re-evaluating whether or not you really need so much flexibility. Do you really need to be able to handle properties of any type? If you can narrow it down to just a few types, you may be able to come up with a solution using inheritance or templates, without having to "fight the language".