Your approach was basically in the right direction. You will need to know the type in which you have invested. You can use boost::any and you can place anything on the map if you know what you have embedded:
std::map<std::string, boost::any> table; table["hello"] = 10; std::cout << boost::any_cast<int>(table["hello"]);
Some answers recommend using boost::variant to solve this problem. But it will not allow you to store arbitrary typed values ββon the map (as you wanted). You need to know the set of possible types. Given this, you can do it more easily:
typedef boost::variant<int, std::string, void*> variant_type; std::map<std::string, variant_type> table; table["hello"] = 10;
This works because boost::variant overloads operator<< for this purpose. It is important to understand that if you want to save what is currently contained in this option, you still need to know the type, as in the case of boost::any :
typedef boost::variant<int, std::string, void*> variant_type; std::map<std::string, variant_type> table; table["hello"] = "bar"; std::string value = boost::get<std::string>(table["hello"]);
The assignment order of a variant is a runtime property of the control flow of your code, but the type used by any variable is determined at compile time. Therefore, if you want to get a value from a variant, you must know its type. An alternative is to use visits as described in the variant documentation. It works because the variant stores code that tells it which type was last assigned to it. Based on this, he decides at runtime to overload the visitor that he uses. boost::variant quite large and not completely standard, and boost::any is standard, but uses dynamic memory even for small types (so slower. an option can use the stack for small types). Therefore, you must trade what you use.
If you really want to put objects in it that differ only in how they do something, polymorphism is the best way to go. You may have a base class from which you get:
std::map< std::string, boost::shared_ptr<Base> > table; table["hello"] = boost::shared_ptr<Base>(new Apple(...)); table["hello"]->print();
To do this, you will mainly need a layout of this class:
class Base { public: virtual ~Base() { }
boost::shared_ptr is the so-called smart pointer. It will automatically delete your objects if you delete them from your map, and nothing else refers to them. Theoretically, you could work with a simple pointer, but using a smart pointer will greatly increase security. Read the shared_ptr manual I'm attached to.