So I have am using a constructor that looks like this:
deduplicator(std::function<void(const std::vector<uint8_t>&, std::vector<uint8_t>&)> chunk_fingerprinter);
and I use this function as the chunk fingerprinter:
void sha1_hash(const std::vector<uint8_t>& data, std::vector<uint8_t>& hash);
And I initialise the object like this:
deduplication::deduplicator dedup = deduplication::deduplicator(harpocrates::hashing::sha1_hash);
Which results in this error:
../src/split-deduplication/split-deduplication.cpp:35:32: error: address of overloaded function 'sha1_hash' does not match required type 'void'
void* hash_func = (void*) &harpocrates::hashing::sha1_hash;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../resolve_symlinks/harpocrates/src/harpocrates/hashing.hpp:34:10: note: candidate function
void sha1_hash(const std::vector<uint8_t>& data, std::vector<uint8_t>& hash);
^
../resolve_symlinks/harpocrates/src/harpocrates/hashing.hpp:40:10: note: candidate function
void sha1_hash(const uint8_t* data, const size_t size, uint8_t* hash);
But if I dabble a bit in the dark arts and do this:
void (*sha1_hash)(const std::vector<uint8_t>&, std::vector<uint8_t>&) = harpocrates::hashing::sha1_hash;
deduplication::deduplicator dedup = deduplication::deduplicator(sha1_hash);
Then it works, can someone explain to me why that is? I am using C++17 if that makes a difference
EDIT:
Made a mistake, I have update the sha1_hash
function to the correct one I call
I had two functions in the same namespace with the same name, as pointe out below, the clean solution in this case was to split into two namespace. And as people have mentioned it was because the compiler could not choose which one to use.
From the error message I suppose that sha1_hash
is overloaded.
void (*sha1_hash)(const std::vector<uint8_t>&, std::vector<uint8_t>&) = harpocrates::hashing::sha1_hash;
works because when taking the address of an overloaded function overload resolution is performed, the overload whose signature matches the type of sha1_hash
is selected, i.e. void (*)(const std::vector<uint8_t>&, std::vector<uint8_t>&)
.
In all these contexts, the function selected from the overload set is the function whose type matches the pointer to function, reference to function, or pointer to member function type that is expected by target: the object or reference being initialized, the left-hand side of the assignment, function or operator parameter, the return type of a function, the target type of a cast, or the type of the template parameter, respectively.
You can also use static_cast
to specify explicitly.
auto sha1_hash = static_cast<void (*)(const std::vector<uint8_t>&, std::vector<uint8_t>&)>(harpocrates::hashing::sha1_hash);
As the error message said, void* hash_func = (void*) &harpocrates::hashing::sha1_hash;
doesn't works because void*
doesn't match either signature of overloaded sha1_hash
, then overload resolution fails.
BTW: Trying to convert the function pointer to void*
seems a bad idea, especially you don't need it at all for this case.