1

I'm trying to create a unordered_map that has an integer as a key and a Transition object as the value.... Here's what I have:

Instantiation

unordered_map<int, Transition> transitions;

Transition Class Declaration:

class Transition{

    public:
            Transition(int n, char r, char m);
            ~Transition();
            int getNextState();
            char getReplacement();
            char getMovement();

    private:
            int nextState;
            char replacement;
            char movement;
};

Adding a transition to the map

// Create transition object
Transition t(r,b,x);
transitions[keyForMap] = t;

I'm getting this error:

/usr/include/c++/4.7/bits/hashtable_policy.h:445:24: error: no matching function for call to ‘Transition::Transition()’
/usr/include/c++/4.7/bits/hashtable_policy.h:445:24: note: candidates are:
In file included from ball_p1.cpp:6:0:
Transition.h:4:3: note: Transition::Transition(int, char, char)
Transition.h:4:3: note:   candidate expects 3 arguments, 0 provided
Transition.h:1:7: note: constexpr Transition::Transition(const Transition&)
Transition.h:1:7: note:   candidate expects 1 argument, 0 provided

Do I need to somehow specify the parameters that the constructor takes somewhere in the instantiation? What am I doing wrong? Thanks for any help ahead of time.

JayB
  • 397
  • 6
  • 21
  • 4
    Usage of `unordered_map::operator[]` requires that the mapped type (`Transition`) can be default-constructed. Use `unordered_map::insert` or `unordered_map::emplace` instead. See [cppreference: `unordered_map::operator[]`](http://en.cppreference.com/w/cpp/container/unordered_map/operator_at) – dyp Feb 06 '15 at 23:58
  • From cppreference about `unordered_map::operator[]`: "Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist." Is anything unclear about the documentation linked above? – dyp Feb 07 '15 at 00:08
  • @dyp I was just concerned that since insert doesn't ask for a key that I wouldn't be able to retrieve the value I wanted when needed. If i just make a key value pair and insert that, does the map use the pair's key for retrieval? – JayB Feb 07 '15 at 00:09
  • 2
    Hm. It seems not to be obvious neither from cppreference nor from the Standard: The `value_type` that `insert` takes is a (key, value) pair. So, `insert` inserts a value specified by the pair at the key specified by the pair. – dyp Feb 07 '15 at 00:12
  • @dyp thanks a lot. if you post this as an answer I can accept it and get you some rep – JayB Feb 07 '15 at 00:15
  • Related: [std::unordered_map with custom value type, `operator[]`](http://stackoverflow.com/q/26800298) (I'm trying to find a duplicate with an answers that shows the alternatives; you'd probably find something for `std::map`, but `std::unordered_map` seems less common) – dyp Feb 07 '15 at 00:19
  • 1
    This seems to contain a nice overview: [insert vs emplace vs `operator[]` in c++ map](http://stackoverflow.com/q/17172080) – dyp Feb 07 '15 at 00:23

3 Answers3

3

I always use map.insert(std::make_pair(keyForMap, transition));.

Aitch
  • 1,617
  • 13
  • 24
  • The key is an int, but I'll try this out – JayB Feb 07 '15 at 00:08
  • 5
    Why not `map.emplace(keyForMap, transition);`? – dyp Feb 07 '15 at 00:09
  • *"f the key is not an int you cannot use operator[]"* Huh? Why? `unordered_map::operator[]` takes the key type of the map as its parameter, which can be something different from an `int`, e.g. a `std::string`. – dyp Feb 07 '15 at 00:14
  • @dyp what's the difference between emplace(keyForMap, transition) and insert(make_pair(keyForMap, transition)) ?? – JayB Feb 07 '15 at 00:14
  • 1
    @JayB Not much, `emplace(a, b)` directly constructs the (key, value) pair from (a, b), whereas `insert(make_pair(a, b))` construct a pair (a, b) and moves that into a pair owned by the map. (I.e., `emplace` omits one step.) – dyp Feb 07 '15 at 00:16
  • Also possible, it's only my preferred way, because for example `map.find(keyForMap)` gives me an iterator pointing to a pair again, so they are everywhere :) – Aitch Feb 07 '15 at 00:22
  • @dyp you are right, I mixed something up. operator[] can be used with any type but only one argument. I think this one is solved. – Aitch Feb 07 '15 at 00:37
0

std::map::operator[] works as follows:
- If the specified key already exists, it returns a reference to the corresponding value.
- If the specified key doesn't exist, it inserts it, assigns it a default value, and return a reference to this recently created instance of the default value.

For example,
map<string, int> m; std::cout << m["new_key"]; // This prints the default value for type int, namely '0'.

If your value type does not support a default value (e.g. if it's a custom class that does not have a default constructor), then you can not use std::map::operator[]. You can, however, use std::map::insert to perform the same functionality. The latter will insert a pair directly into your map, without passing by the intermediate step of creating a default value.

0

Your constructor got rid of the default constructor (which is needed).

JobHunter69
  • 1,706
  • 5
  • 25
  • 49