I was just toying with search algorithms a while ago and after a few benchmarks, I was impressed to see how much faster the old bsearch() was comparend to std::binary_search(). I thought that any decent compiler would be able to replace std::binary_search() by bsearch() when possible, but even though I’m using GCC 4.7, bsearch seems to perform something like 5 times faster than std::binary_search.
So I thought that it would be a great exercise trying to create some kind of wrapper for bsearch with the same interface then std::binary_search. But for an unknown reason, I did not manage to do it. Here’s my code:
template<typename InputIterator, class T>
bool binary_search(InputIterator first, InputIterator last, const T& value)
{
auto cmp = [](const void* a, const void* b)
{
return (int) ((*(T*)a) == (*(T*)b));
};
std::cout << value << std::endl;
T* res = (T*) bsearch(&value, first, last-first, sizeof(*first), cmp);
return res != nullptr;
}
The code compiles fine and does not crash at execution. However, it seems that bsearch stops right after one internal iteration (*res is always equals to the value at the middle of the tab passed as parameter). I can’t manage to find why it does not work. So, if possible, a little help would be fine.
Thanks.
For those who ask for the code used to check the speed:
const std::string keyword_str[] = {
// Some strings
};
int cmp(const void* s1, const void* s2)
{
return (int) ((*(std::string*)s1) == (*(std::string*)s2));
}
int main()
{
time_t start, end;
double dif;
time (&start);
// Code
for (const string& str: keyword_str)
{
for (size_t i = 0 ; i < 1000000 ; ++i)
{
// std::binary_search (uncomment to check)
//bool a = std::binary_search(keyword_str, keyword_str+28, str);
// bsearch
char** st = (char**) bsearch(&str, keyword_str, 28, sizeof(keyword_str[0]), cmp);
}
}
time (&end);
dif = difftime (end, start);
printf("Time spent: %fs.\n", dif);
return 0;
}
bsearchtakes a function pointer, andcmpis not a function pointer. (EDIT: I was wrong about this. Sincecmpdoesn’t capture any variables — it’s brackets are empty — it can be passed as a function pointer. This behavior is specified in §5.1.2/6 of the C++11 standard.)bsearchalso doesn’t return the right values that the comparison function is expected to return. It should return -1 if the key is less than the array element, 0 if they are equal, and 1 if the key is greater than the array element. Yourcmpfunction returns 0 if they are inequal and 1 if they are equal. As a result, if the first element you’re comparing is inequal to the key, then yourcmpmakesbsearchthink they’re equal andbsearchstops because it thinks it found the right element immediately.