В C ++ есть две версии qsort()
предоставляется стандартной библиотекой:
extern "C" void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
extern "C++" void qsort(void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*));
bsearch()
примерно так же.
Мой вопрос, как работает разрешение перегрузки при вызове qsort()
? Будет ли он автоматически ссылаться на соответствующую функцию на основе типа связи («C» или «C ++») указателя функции, переданного в качестве последнего аргумента? Или вызывающий должен указать явно с каким-то дополнительным синтаксисом?
(Давайте просто уберем искушение позвонить std::sort
на секунду…)
int (*compar)(const void*, const void*)
Параметр имеет разные типы для двух разных перегрузок. Для первой перегрузки это extern "C"
параметр указателя функции. Для второй перегрузки это extern "C++"
параметр указателя функции. Любой указатель на функцию, которую вы передаете qsort
уже будет иметь какую-то связь, и это то, что используется, чтобы определить, какую перегрузку вызывать.
Чтобы процитировать стандарт:
7.5 Спецификации сцепления [dcl.link]
Все типы функций, имена функций с внешней связью и имена переменных с внешней связью имеют языковая связь. […] Языковая связь по умолчанию для всех типов функций, имен функций и имен переменных — это языковая связь C ++. Два типа функций с разными языковыми связями являются разными типами, даже если они идентичны.
На самом деле, я не думаю, что стандарт на самом деле означает, что два qsort
перегрузки действительно имеют различную связь. В отличие от C, пользовательские объявления стандартных функций библиотеки не допускаются; соответствующая разница между ними является тип compar
, Они могли быть объявлены
extern "C" typedef int (*__compar_fnp_c)(const void *, const void *);
extern "C++" typedef int (*__compar_fnp_cxx)(const void *, const void *);
void qsort(void* base, size_t nmemb, size_t size, __compar_fnp_c compar);
void qsort(void* base, size_t nmemb, size_t size, __compar_fnp_cxx compar);
где должно быть более очевидно, что __compar_fnp_c
а также __compar_fnp_cxx
разные типы. Тем не менее, правило «как если» не допускает такую реализацию, поскольку оно нарушит код, который принимает указатель или ссылку на qsort
,
Обратите внимание, что GCC, как и некоторые другие компиляторы, не реализуют это правильно и не рассматривают связывание как часть типа указателя функции. На таких реализациях только одна версия qsort
будет сделано доступным, чтобы предотвратить конфликт при разрешении перегрузки.
Других решений пока нет …