How to Make a Heterogeneous Boost::Map

how do you make a heterogeneous boost::map?

#include <map>
#include <string>
#include <iostream>
#include <boost/any.hpp>

int main()
{
try
{
std::map<std::string, boost::any> m;
m["a"] = 2;
m["b"] = static_cast<char const *>("black sheep");

int i = boost::any_cast<int>(m["a"]);
std::cout << "I(" << i << ")\n";

int j = boost::any_cast<int>(m["b"]); // throws exception
std::cout << "J(" << j << ")\n";
}
catch(...)
{
std::cout << "Exception\n";
}

}

Boost how to create a map for types selection?

For that, you would need a heterogeneous map - that is, its elements can be of different types. Furthermore you would need the ability to return types from functions, not just variables.


Now, a heterogeneous map would be possible with Boost.Variant or a simple union, but that binds it to compile time: we need to know every type that is possible to create that variant/union.

Of course a Boost.Any would be possible to store everything and its dog, but the problem strikes again: you need to extract the real type out of that Boost.Any again. The problem repeats itself. And if you know the real type, you can aswell just make a variant/union and save yourself the any_cast trouble.


Now, for another troublesome thing:

m.get<myMap["TYPE_1_IN_STRING_FORM"], myMap["TYPE_2_IN_STRING_FORM"]>

To make the above line work, you'd need two features that C++ doesn't have: the ability to return types and runtime templates. Lets ignore the first point for a moment.

Templates are compile-time, and the get function is such a template. Now, to use that template, your myMap would need to be able to return types at compile-time, while getting populated at runtime. See the contradiction? That's why runtime templates would be needed.


Sadly, exactly those three things are not possible (or extremely hard and very very limited) in C++ at runtime: heterogeneous data types (without constant size), returning types and templates.

Everything that involves types needs to be done at compile-time. This blogpost by @Gman somewhat correlates with that problem. It's definitly worth a read if you want to know what C++ just can't do.


So, to conclude: You'll need to rethink and refactor your problem and solution. :|

c++ std::map of heterogeneous function pointers

Each of your functions has a different type, so you need some kind of type erasure. You could use the most generic of them: Boost.Any. You can have a map of boost::any, but you need to know the type of the function in order to get it back and call it.

Alternatively, if you know your arguments ahead of time you can bind them with the function call and have all functions in the map be nullary functions: function< void() >. Even if you don't, you may be able to get away with it by binding the argument to references, and then at call time fill the referred variables with the appropiate arguments.

Deserializing a heterogeneous map with MessagePack in C++

I ended up punting on this and writing my own text-based serialization format. It’s not generally useful like MessagePack is, but it allows me to paper over these static-typing woes.

What are the ways to implement a map of heterogeneous functions in Java?And their pros and cons?

  1. there are no function pointers in java, only interfaces
  2. imo reflection is not as slow and ugly as many people think
  3. you still need to know how to call the function (you need to know that in c++ too)
    so having the same signature is not that bad, just take a very flexible signature like
    void command(Object... args)

Edit:
about Reflection performance:
look at this threads answer: Java Reflection Performance

you can see that just calling a reflection object is not that slow, it's the lookup by name that costs alot of time, and i think i your case you dont need that more than once per function

Heterogeneous containers in C++

Well generally C++ Containers are designed to hold objects of a single type using templates. If you want different types that are all derived from one type you can store a container of pointers (I guess you could also have a container of void* to anything...) e.g. std::vector<MyBaseType*>.

If you want completely unrelated types, you can store objects that can safely reference those other types, such as boost::any.

http://www.boost.org/doc/libs/1_47_0/doc/html/any.html

Some examples off the boost site:

#include <list>
#include <boost/any.hpp>

using boost::any_cast;
typedef std::list<boost::any> many;

void append_int(many & values, int value)
{
boost::any to_append = value;
values.push_back(to_append);
}

void append_string(many & values, const std::string & value)
{
values.push_back(value);
}

bool is_int(const boost::any & operand)
{
return operand.type() == typeid(int);
}
bool is_char_ptr(const boost::any & operand)
{
try
{
any_cast<const char *>(operand);
return true;
}
catch(const boost::bad_any_cast &)
{
return false;
}
}

boost::variant is similar, but you specify all the allowed types, rather than allowing any type in your container.

http://www.boost.org/doc/libs/1_47_0/doc/html/variant.html

std::vector< boost::variant<unsigned, std::string> > vec;
vec.push_back( 44);
vec.push_back( "str" );
vec.push_back( SomthingElse(55, 65) ); //not allowed


Related Topics



Leave a reply



Submit