Jaideep Shekhar
Jaideep Shekhar

Reputation: 886

how to declare variable using typeinfo.name C++

I love coding, and generally do so in Python due to its simplicity and power.
However, for some time critical programs/tasks, I use C++.
Therefore, to get best of both worlds, I am making a Pythonesque list in C++.

AIM: I would like to be able to add any variable or value of any data type, including classes user has defined.
To do this, I have a structure item with a char * value, a char * type and an int size.
My List has an array of these item * s.


Now, I have taken the variable in a template function:
template<class T> item * encode(const T& var);
and declared a pointer to item item * i = new item;

And, I have stored the values of these variables as c style strings.
For example, 14675 in binary is 0000 0000 0000 0000 0011 1001 0101 0011
Therefore, I have dynamically created space, like so:
i->size = sizeof(var);
i->value = new char[i->size]; //4 in this case
and set each bit in value with respective bits in var.

I have also stored their types as
i->type = typeinfo(var).name();
So far so good!


Now, I am stuck with auto decode(item * i) -> decltype(/*What goes here???*/)
How do I specify the return type of the function?
Is there any possible way?
Preferably using the i->type?
Or, should I make changes in the basic design of this process?
Thanks in advance!

Upvotes: 1

Views: 1565

Answers (1)

besc
besc

Reputation: 2647

Answering your question

I would like to be able to add any variable or value of any data type, including classes user has defined.

Without cooperation from the user that’s impossible in C++.

Remember that C++ types are a compile-time concept only. They do not exist at runtime. The only type information available at runtime is the thin layer of RTTI provided by typeid(). Runtime duck-typing like in Python is not possible.

You can create a container of arbitrary objects quite easily.

std::vector<std::any> v;  // requires C++17

However the user of that container has to know what index contains what type:

if (v[0].type() == typeid(ArbitraryUserType)) {
    const auto& item = std::any_cast<ArbitraryUserType>(v[0]);
    // work on item ...
}

Because of the compile-time nature of types you as the library writer cannot perform that any_cast. It has to be spelled out in the user’s source code.

In general, don’t try to shoehorn a pythonic mindset into C++. It never ends well, especially when you try to circumvent one of the most basic foundations of C++: its powerful static type system.

Notes:

  • Without C++17 you could use boost::any.
  • If you know the list of possible types at compile-time std::vector<std::variant<Type1, Type2, etc>> is a good alternative. With any the user is fully responsible to keep track of their types. Because all type checks happen at runtime the compiler cannot help. Variant on the other hand brings back a large chunk of the compile-time safety. And again there’s boost::variant as a non-C++17 alternative.

Notes on your encoding approach

Basically you’re trying to serialize (encode) and deserialize (decode) arbitrary types. Without cooperation from those types, that’s not possible.

Your approach only works for trivial types that can be copied bit by bit. C++ even has a type trait for that: std::is_trivially_copyable. In the end you support fundamental types and C-style structs of those, but nothing else.

Imagine the T for your encode() function was std::string. Simply put a std::string contains a pointer to a separately allocated piece of memory where the actual string data is stored. The string object itself is just a managing wrapper for that pointer. encode() only serializes the wrapper object, but not the pointed-to memory block with the actual data.

Even if during deserialization you could instantiate arbitrary types from a stream of bits, the stream is not complete. What you’d have to implement is a C++ version of Python’s copy.deepcopy, which is impossible without cooperation from each type. Have a look at a C++ serialization library – take Cereal as a straight-forward example – to see how that cooperation can look in practice.

Upvotes: 1

Related Questions