为什么使用“std::lower_bound”可以在没有标头“算法”的情况下工作,但包含一些其他标头(而“std::upper_bound”则不能)?

问题描述 投票:0回答:1

以下代码(使用 C 样式数组不必包含其他标头):

int main() {
    int a[] = {1, 2, 3, 4, 5};
    std::lower_bound(a, a + 5, 2);
    return 0;
}

预期会导致错误(使用

g++ -std=c++98 -Wall -Wextra
编译时,'lower_bound'不是'std'的成员,使用
clang++ -std=c++98 -Wall -Wextra
未声明的标识符'std')。

但是,通过简单地包含标头之一,例如

iostream
vector
queue
stack
(以及容器库中的其他标头),即可编译(仅带有有关未使用结果的警告)。

这让我感到惊讶,因为非成员

std::lower_bound
(此处使用的)是在
algorithm
标头中实现的,而该标头未包含在内。此外,将
lower_bound
更改为
upper_bound
会导致编译器错误“命名空间 'std' 中没有名为 'upper_bound' 的成员;您的意思是 'lower_bound'”(对于两个编译器),无论标准如何,直到 C++20它在其中起作用。

编译器版本是:

g++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0

Ubuntu clang version 14.0.0-1ubuntu1.1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

/usr/include/c++
内Grepping“lower_bound”并在那里和编译器源代码中搜索,我无法找到可以在此处调用哪个确切函数。

c++
1个回答
0
投票

正确答案:运气

如果您没有显式包含所需符号的标头,则任何其他间接包含该符号的标头对您来说纯粹是运气。

符号的选择(如

std::lower_bound
vs
std::upper_bound
)仅仅意味着你遇到了魔法。标准标头通常不是单独的整体文件,但它们本身会引入许多额外的特定于实现的包含文件,这些文件执行声明各种符号的实际工作。

因此,标准头文件之一(用于您的实现)完全有可能包含定义

std::lower_bound
但不定义
std::upper_bound
的内容。

重要的警告是:标准头文件包含的内容可能会更改对于编译器/库/任何未来(或过去)版本的编译器/库/任何东西!此外,您获得的版本可能不是完整的标准版本 -定义版本!并且期望它与其他编译器一起工作也是不合理的!

换句话说,如果您没有显式包含所需的标头,则不要期望访问标准定义的标准库函数。

© www.soinside.com 2019 - 2024. All rights reserved.