1

consider the following code:

namespace fruit { struct apple{ ... }; } namespace language{ struct english{ ... }; } 

I want to do something like:

std::unordered_map<std::string, ? > mymap = { {"paul", {"like", fruit::apple} }, {"jonas", {"like", language::english} } }; 

the key of my map is a string and the value should be such a pair <string, ? >.
What type should I give as value for my map? I think things like union or functor can be used to solve the problem, but how? thanks in advance.

5
  • 1
    Looks like you want std::variant or std::any Commented Aug 3, 2018 at 13:19
  • 3
    What's the goal of the exercise? How do you envision using mymap, once constructed? Sounds like an XY problem Commented Aug 3, 2018 at 13:40
  • Naive solution would be std::tuple<std::string,std::unique_ptr<fruit::apple>,std::unique_ptr<language::english>> and make either nullptr Commented Aug 3, 2018 at 13:59
  • Use factory pattern and register each object (fruit::apple, language::english etc). Use functor in the unordered_map. You may need proxy pattern to wrap the object before hand so that you can apply inheritance. Commented Aug 3, 2018 at 14:16
  • @seccpur can you provide an example? thanks Commented Aug 3, 2018 at 14:19

4 Answers 4

2

Here's a snippet ( without the factory pattern => improve the syntax ) with proxy pattern so that you need not modify your existing objects:

struct base { }; namespace fruit { struct apple {}; struct apple_proxy: base { apple_proxy() :apple_ptr(make_shared<fruit::apple>()) {} shared_ptr<apple> apple_ptr; }; } namespace language { struct english {}; struct english_proxy : base { english_proxy() :english_ptr(make_shared<language::english>()) {} shared_ptr<english> english_ptr; }; } int main() { std::unordered_map<std::string, shared_ptr<base>> map; shared_ptr<fruit::apple_proxy> a = make_shared<fruit::apple_proxy>(); map.emplace(make_pair("apple",a)); shared_ptr<language::english_proxy> e = make_shared<language::english_proxy>(); map.emplace(make_pair("english", e)); } 
Sign up to request clarification or add additional context in comments.

Comments

1

This code compiles for me:

#include <unordered_map> #include <utility> #include <variant> namespace fruit { struct apple{}; } namespace language{ struct english{}; } int main(){ std::unordered_map<std::string,std::pair<std::string,std::variant<fruit::apple, language::english> > > mymap { {"paul", {"like", fruit::apple()} }, {"jonas", {"like", language::english()}} }; } 

Note that you may want to compile with something like -std=gnu++17.

5 Comments

std::variant<fruit::apple, language::english> -i'm limited to c++11 -There is like 30 type as fruit::apple, language::english, .., It will be inconvenient to write them all in the map declaration.. is there another way?
Then use boost::variant
Can u use polymorphism? You may want to make both fruit::apple and language::english inherit from same base class and instead of using std::variant you would use the base class.
@Antua i can't use polymorphism. In my real case scenario, both fruit::apple and language::english have been designed years ago.. and don't inherit from any class..
Then construct your own wrapper. No other solution comes to my mind.
1

So I found a solution using std::type_index.

typedef std::pair<std::string, std::type_index> myPair; std::unordered_map<std::string, myPair> myMap = { {"paul", {"likes", std::type_index(typeid(fruit::apple))} }, {"jonas", {"likes", std::type_index(typeid(language::english))} } }; 

thanks guys for your valuable suggestions.

Comments

0

If you cannot use std::variant or boost::variant this solution could work:

struct data { std::string action; std::unque_ptr<fruit::apple> apple; std::unque_ptr<language::english> english; data( std::string act, fruit::apple ap ) : action( std::move( act ) ), apple( std::make_unqiue<fruit::apple>( std::move( ap ) ) {} data( std::string act, language::english en ) : action( std::move( act ) ), english( std::make_unqiue<language::english>( std::move( en ) ) {} }; 

but most probably your problem has better solution.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.