-1

i get so many different issues trying to use STL maps, it is really discouraging

so i got many questions:

  • first i had a problem with some " < operator not defined", but i did not need any ordering in my maps(why would anyone need that by default anyway) so i found unordered_map but i have to use c++11 or something, don't know what it means and i am not sure this is a good idea, is it standard c? is it portable ?

  • then i got some weird error:

    /usr/include/c++/4.8/bits/hashtable_policy.h:1070:12: error: invalid use of incomplete type ‘struct std::hash< FOLVariable>’

so why is the template so intrusive? i mean it should act as a container, not minding what is the object about nor what is inside of it

anyone can help me out with this error?

thanks

Phil
  • 708
  • 1
  • 11
  • 22

2 Answers2

0

map stores its elements ordered by key; so you need to define that ordering.

If the key is a class type, you can either overload operator< so that the default ordering of std::less works:

bool operator<(my_thing const & a, my_thing const & b) {
    // return true if "a" is ordered before "b"
}

std::map<my_thing, something_else> my_map;

or you can provide your own comparison functor

struct compare_my_thing {
    bool operator()(my_thing const & a, my_thing const & b) {
        // return true if 'a' is ordered before 'b'
    }
};

std::map<my_thing, something_else, compare_my_thing> my_map;

unordered_map is a hash table; so you need to define both a hash function and a means to compare for equality (since hashes are generally not unique). Again, you can either provide overloads so that the defaults (std::hash and std::equal_to) work:

namespace std {
    template <>
    struct hash<my_thing> {
        std::size_t operator()(my_thing const & t) const {
            // return hash of 't'
        }
    };
}

bool operator==(my_thing const & a, my_thing const & b) {
    // return true if 'a' and 'b' are equal
}

std::unordered_map<my_thing, something_else> my_map;

or you can provide your own functors

struct hash_my_thing {
    std::size_t operator()(my_thing const & t) const {
        // return hash of 't'
    }
};

struct compare_my_thing {
    bool operator()(my_thing const & a, my_thing const & b) {
        // return true if 'a' and 'b' are equal
    }
};

std::unordered_map<my_thing, something_else, hash_my_thing, compare_my_thing> my_map;

so why is the template so intrusive? i mean it should act as a container, not minding what is the object about nor what is inside of it

Different containers have different requirements from their contained types. For example, yhey all require them to be destructible, since containers are responsible for managing their lifetime. Some require them to be movable; for example, vector needs to move elements when allocating a larger array to keep them in. Associative containers have extra requirements on their key types, to allow them to be used as keys.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • ok, thanks for this complete answer, but why not simply base the comparison/sorting... on the pointer address for objects ? – Phil Mar 24 '14 at 15:30
  • 1
    Because you're not storing pointers. – Bart van Nierop Mar 24 '14 at 15:32
  • @user3455897: Because that would check for *identity* not *equivalence* or *equality*. `find(some_key)` would never succeed, because `some_key` itself is not in the map. – Mike Seymour Mar 24 '14 at 15:35
  • - but for the "struct compare_my_thing {" example, the operator should be == right ? - also is it possible to declare the hash<> and == operators in the class itself? instead of using struct... – Phil Mar 24 '14 at 16:03
  • "the operator should be == right ?" - No. It's a functor, called via its `()` overload. – Mike Seymour Mar 24 '14 at 16:05
  • "also is it possible to declare the hash<> and == operators in the class itself?" The operators, yes. They can be members with a single argument, rather than non-members with two: `bool operator<(my_thing const & other) const`. I don't think `hash` can be a member. – Mike Seymour Mar 24 '14 at 16:07
  • and can i declare these inside a class? – Phil Mar 24 '14 at 16:08
  • @user3455897: Yes, if they're members. – Mike Seymour Mar 24 '14 at 16:09
0

first i had a problem with some " < operator not defined", but i did not need any ordering in my maps(why would anyone need that by default anyway)

From the documentation:

std::map is a sorted associative container that contains key-value pairs with unique keys. Keys are sorted by using the comparison function Compare.

Emphasis mine. By default, the comparison function is operator <.

so i found unordered_map but i have to use c++11 or something, don't know what it means and i am not sure this is a good idea, is it standard c? is it portable ?

C++11 is the name of the latest C++ standard. Most modern compilers support most major features of that standard by now. If your compiler supports it, then it's a good idea to use the features that you require. It's not standard C, but it is standard C++.

then i got some weird error:

/usr/include/c++/4.8/bits/hashtable_policy.h:1070:12: error: invalid use of incomplete type ‘struct std::hash< FOLVariable>’

std::unordered_map is a hash table. By default, the hashing function used for a std::unordered_map<Key, Value> is a specialization of std::hash<Key>. You get the error because no such specialization exists for your type FOLVariable.

Community
  • 1
  • 1
Bart van Nierop
  • 4,130
  • 2
  • 28
  • 32
  • thanks for the answer, sorry for the duplicate, i honestly could not find the previous thread about the same issue – Phil Mar 25 '14 at 12:41