以下代码(使用 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”并在那里和编译器源代码中搜索,我无法找到可以在此处调用哪个确切函数。
正确答案:运气
如果您没有显式包含所需符号的标头,则任何其他间接包含该符号的标头对您来说纯粹是运气。
符号的选择(如
std::lower_bound
vs std::upper_bound
)仅仅意味着你遇到了魔法。标准标头通常不是单独的整体文件,但它们本身会引入许多额外的特定于实现的包含文件,这些文件执行声明各种符号的实际工作。
因此,标准头文件之一(用于您的实现)完全有可能包含定义
std::lower_bound
但不定义 std::upper_bound
的内容。
重要的警告是:标准头文件包含的内容可能会更改对于编译器/库/任何未来(或过去)版本的编译器/库/任何东西!此外,您获得的版本可能不是完整的标准版本 -定义版本!并且期望它与其他编译器一起工作也是不合理的!
换句话说,如果您没有显式包含所需的标头,则不要期望访问标准定义的标准库函数。