【问题标题】:Is the specification of `bsearch` in C++11 & C++14 defective?C++11 和 C++14 中的 `bsearch` 规范有缺陷吗?
【发布时间】:2014-11-27 10:48:34
【问题描述】:

在我对this question 的回答之后,在 C++11 和 C++14 中:

[C++11, C++14: 25.5/2]: 内容与标准 C 库头 <stdlib.h> 相同,但有以下例外:

[C++11, C++14: 25.5/3]:函数签名:

bsearch(const void *, const void *, size_t, size_t,
        int (*)(const void *, const void *));

替换为两个声明:

extern "C" void *bsearch(const void *key, const void *base,
                         size_t nmemb, size_t size,
                         int (*compar)(const void *, const void *));

extern "C++" void *bsearch(const void *key, const void *base,
                           size_t nmemb, size_t size,
                           int (*compar)(const void *, const void *));

两者都具有与原始声明相同的行为。

然而,

[C++11, C++14: 7.5/5]: 如果两个声明将具有相同名称和参数类型列表 (8.3.5) 的函数声明为相同命名空间的成员,或者将具有相同名称的对象声明为相同命名空间的成员,则声明给名称不同的语言链接,程序格式错误;如果声明出现在不同的翻译单元中,则不需要诊断。 [..]

这是缺陷吗?

【问题讨论】:

  • 答案取决于这两个函数是否具有相同的参数。如果链接是类型的一部分,compar 在两个示例中都有不同的类型......虽然如果是,我想要一些简单的方法来为类型声明它,我不知道。
  • @Deduplicator 在标准 C++ 中,您可以使用模板别名。 template <typename R, typename...T> using CxxFunc = R(T...); extern "C" { template <typename R, typename...T> using CFunc = R(T...); }。将compar 声明为CFunc<int, const void *, const void *>CxxFunc<...>。大多数实现都拒绝它,因为它们不允许 extern "C" 块中的模板,但它是完全有效的。限制是模板不能有extern "C" 链接,而不是模板不能出现在extern "C" 块中。模板别名没有语言链接,所以没关系。
  • 在 C++98 25.4/3 中也是一样的(qsort 是 25.4/4)

标签: c++ c++11 language-lawyer c++14 bsearch


【解决方案1】:

但参数类型列表不一样。一种,compar 是指向具有“C”语言链接的函数的指针,另一种是指向具有“C++”语言链接的函数的指针。

C++11, 7.5 规定:

1 ... 两种不同语言的函数类型 链接是不同的类型,即使它们在其他方面相同。

4 在 linkage-specification 中, 指定的语言链接适用于函数 所有函数声明符的类型、带有外部链接的函数名和带有外部链接的变量名 链接规范中声明的链接。 [示例:

extern "C" void f1(void(*pf)(int));
// the name f1 and its function type have C language
// linkage; pf is a pointer to a C function

7.5/1 和 7.5/5 之间看似不一致的问题在意识到 1 谈论函数类型而 5 谈论函数名称时得到解决。

【讨论】:

  • 对于需要两个函数指针的函数,是否有任何简单的方法可以声明第一个 fp 具有 C++ 和第二个 C 链接?
  • @Deduplicator 使用typedef 作为与包含函数的语言链接不同的参数。
  • 似乎clang++和g++都不认为它们不同。 coliru.stacked-crooked.com/a/ceb69c605e32832d
  • 好吧,如果他们无法区分链接上的类型,他们别无选择。所以,一个错误并充分利用它。
  • @Yakk 无法记住函数类型语言链接是一个明确的一致性问题,对此毫无疑问。是的,当您使用指向任何标准库函数的指针时,您不能假定任何特定的语言链接。你可能会得到一个带有 C 链接的函数,或者一个带有 C++ 链接的函数,你可以使用它的唯一方法是在任何一个都可以工作的上下文中(decltypeauto 或推导出的模板参数)
猜你喜欢
  • 2012-05-22
  • 1970-01-01
  • 2014-07-30
  • 1970-01-01
  • 2018-01-28
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
相关资源
最近更新 更多