qsort()/ bsearch()的extern“C”和“C ++”版本的重载分辨率

时间:2014-02-22 13:57:52

标签: c++ qsort bsearch

在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一秒钟的诱惑......)

1 个答案:

答案 0 :(得分:3)

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是不同类型的更明显的地方。也就是说,as-if规则不允许这种实现,因为它会破坏带有指针或引用qsort的代码。

请注意,GCC以及其他一些编译器没有正确实现,并且不将链接视为函数指针类型的一部分。在此类实现中,只有一个版本的qsort可用,以防止在重载解析期间发生冲突。