serge-sans-paille/frozen

unordered_set<string> won't compile

ISilviu opened this issue · 5 comments

I'm trying to compile a simple unordered_set consisting of strings.

#include <frozen/string.h>
#include <frozen/unordered_set.h>

int main()
{
	constexpr frozen::unordered_set<frozen::string, 4> extensions = {".h", ".cpp", ".hpp", ".cc" };
	return 0;
}

I'm using MSVC 19.16.27026.1 with C++17 enabled and it generates the following error message: "expression did not evaluate to a constant".

I have also tried to compile it with clang 7.0.1 and it won't compile either, giving the following message: "constexpr variable 'extensions' must be initialized by a constant expression".

Finally, I gave a shot to GCC 6.3.0 and it gave me: "cc1plus.exe: out of memory allocating 65536 bytes".

I must mention that I've tried to use the olaf hash functor, but that had no effect.

Could you help me?

Hi, I don't see anything obviously wrong with your code, but I know we have a unit test that tests examples like yours and also more complex examples:

https://github.com/serge-sans-paille/frozen/blob/master/tests/test_unordered_str_set.cpp

and it passed not so long ago against clang 5: https://travis-ci.org/serge-sans-paille/frozen/jobs/477004765

Can you confirm that you are using the latest version of frozen?

I've run that test and it passed.

Yes, I believe I'm using the latest version of Frozen. I cloned the repo yesterday.

@ISilviu this sometimes happen when the hash function does not provide enough variablility for the given input set. Changing the hash function can help getting nice speedup and better compilation time. In your case

struct hasher {
constexpr std::size_t operator()(frozen::string const &value, std::size_t seed) const {
    return seed  ^ value.size() ^ value[1];
}
};

is a good catch, see https://godbolt.org/z/h-l3n8

I suspected that it's all about the hash function.

Thank you, this one seems to solve the problem. Nonetheless, I would recommend you mention this problem in the Troubleshooting section of your Readme.

@ISilviu it's already the case

or the hash functions used by frozen do not suit your data, and you should change them, as in the following:

struct olaf {
  constexpr std::size_t operator()(frozen::string const &value, std::size_t seed) const { return seed ^ value[0];}
};

constexpr frozen::unordered_set<frozen::string, 2, olaf/*custom hash*/> hans = { "a", "b" };

feel free to propose a better wording as a PR :-)