Параметр 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
, чтобы предотвратить конфликт во время разрешения перегрузки.
person
Community
schedule
22.02.2014