6

qsort()在 C++ 中,标准库提供了两个版本:

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......)

4

1 回答 1

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 以及其他一些编译器没有正确实现这一点,并且不将链接视为函数指针类型的一部分。在这样的实现中,只有一个版本的qsortwill 可用,以防止在重载解决期间发生冲突。

于 2014-02-22T14:01:19.007 回答