-5

I have a struct

struct Key {
    double x;
    double y; 
    double z;

    bool operator==(const Key& k) const{
      return (x == k.x && y == k.y && z == k.z);
    }
}

I do this because I want to make this as key for the hash map.

Then I do

std::unordered_map<Key, int> map = {{1.01, 2.02, 3.03}, 333};

and I want to use initialization list as constructor but I get error no matching constructor for initialization of 'std::unordered_map<key, int> map = {{1.01, 2.02, 3.03}, 333};'

pokche
  • 1,141
  • 12
  • 36
  • How are you expecting the system to build an unordered map when all it can do is compare keys for equality? What would it map based on? – David Schwartz Nov 18 '16 at 19:49
  • I don't know what kind of compiler you have, but `gcc` outputs a quite understandable message [`error: no match for call to '(const std::hash) (const Key&)'`](http://ideone.com/7gm9Tk). – n. m. could be an AI Nov 18 '16 at 19:52
  • 2
    Please provide a [mcve]. This is not one. – Barry Nov 18 '16 at 19:53
  • 1
    I reopened this question because the linked question addresses one but not all of the issues here. There were two other issues, one the OP addressed (int vs double) and one that is addressed in the answers (too few braces.) – templatetypedef Nov 18 '16 at 19:53
  • @n.m. I am using clang++ – pokche Nov 18 '16 at 19:55
  • ok so you do have a hash function defined. – n. m. could be an AI Nov 18 '16 at 20:07
  • @n.m. Yes but I did not include that because I was trying to reduce the complexity of questions – pokche Nov 18 '16 at 20:08
  • reducing complexity below the threshold where the issue is not reproduced is not good. Instead, do `namespace std { template<> struct hash { std::size_t operator()(Key const&)const{return 0;}};}`, which is both as simple as a hash gets and eliminates an error. Ideally you want to compile *just what you post* and *get exactly the error you display*, and what you post to be *minimal*. I happened to read your mind to spot what the real error is; but you want to avoid requiring telepaths to answer your questions. They are thin on the ground. – Yakk - Adam Nevraumont Nov 18 '16 at 20:10
  • And just the opposite has happened. Everyone has assumed you don't have hash, and even closed the question based on that. Which is why [mcve] is not just a good idea, it's the law. – n. m. could be an AI Nov 18 '16 at 20:10
  • @Yakk Thank you for the answer and elaborated comment. I will remember from now on :) – pokche Nov 18 '16 at 22:06

2 Answers2

6

Try {{{1.01, 2.02, 3.03}, 333}} instead of {{1.01, 2.02, 3.03}, 333}

Containers can be initialized with lists of elements, not with instructions on how to construct one element.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
5

There are a number of issues here.

First, you haven't defined a hash function for your Key type. To use Key as a key in an unordered_map, you need both an equality operator (which you've made) and a specialization of std::hash, which you haven't done yet. So you'll need to do something like this:

namespace std {
    template <> struct hash<Key> {
        unsigned operator()(const Key& arg) const {
            return /* some hash code */
        }       
    };
}

Second, you have too few levels of braces in your initializer list. The initializer list expected is a list of key/value pairs, so if you want to use a single key-value pair as the initial map contents, you'll need extra braces:

std::unordered_map<Key, int> map = {{{1.01, 2.02, 3.03}, 333}};

This compiles with these changes; see this demo for confirmation.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • We do not know if there is or is not a hash functor. The only error message provided does not indicate that the hash functor is missing. You are also missing a set of braces. – NathanOliver Nov 18 '16 at 19:57
  • Is there any reason you use `namespace std` instead of `std::hash`? – pokche Nov 18 '16 at 19:58
  • @NathanOliver Oh, good catch on the braces - I copied-and-pasted them from the original and forgot to make edits. And you're right - we don't know this for sure, but given that the OP included the entire class definition I suspected that they likely didn't include it. – templatetypedef Nov 18 '16 at 19:58
  • @pokche The `unordered_map` constructor defaults to using `std::hash` specialized on the key type as its hash type. This means that if you want to specify a hash function, the way to do so is to provide a specialization of `std::hash`, so we enter `namespace std`, then specialize the type `hash` within it. – templatetypedef Nov 18 '16 at 19:59
  • @NathanOliver (Based on the OP's comment here I suspect they did not define a hash function type.) – templatetypedef Nov 18 '16 at 19:59