The Bitcoin codebase has a simple Bloom filter implementation you can take a look at that has been in use for some time
https://github.com/bitcoin/bitcoin/blob/master/src/bloom.h
https://github.com/bitcoin/bitcoin/blob/master/src/bloom.cpp
This proposal decouples the implementation of hash functions from how types get hashed.
[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n398...
template< class Key, class Hash = std::hash<Key> > class BloomFilter;
Minor nit: it will save readers time if you call out that "p is the false positive error rate". (You reference the error rate, but don't attach a variable name to it.) I had to go to an external reference to figure that out, which meant I learned something else of course.
[0] - https://github.com/EricLagergren/bloom [1] - https://github.com/EricLagergren/bloom-c