intabs(int) 与 doubleabs(double)
我想从 C++ 标准的角度(GCC 9.3)了解以下代码的行为,C++20):
#include <cstdlib>
template<class> struct type_tester;
int main() {
type_tester<decltype(abs(0.1))>{}; // int abs(int) overload is selected for some reason!
type_tester<decltype(std::abs(0.1))> {}; // double abs(double) overload is selected, as one would expect
}
因此,int abs(int)
被导入到全局命名空间,而 double abs(double)
则不是!
为什么?
I'd like to understand the behavior of the following code, from the C++ Standard point of view (GCC 9.3, C++20):
#include <cstdlib>
template<class> struct type_tester;
int main() {
type_tester<decltype(abs(0.1))>{}; // int abs(int) overload is selected for some reason!
type_tester<decltype(std::abs(0.1))> {}; // double abs(double) overload is selected, as one would expect
}
So, int abs(int)
is imported to the global namespace, while double abs(double)
is not!
Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
cstdlib
是 C 标头stdlib.h
的 C++ 版本。此类标头必须在std
命名空间中引入名称,并且允许在全局命名空间中引入它们。 C 头文件中没有 double abs(double) ,因此没有理由像函数的 C 变体那样将其引入全局命名空间。请注意,C 没有命名空间,将函数放在全局命名空间中有助于与 C 代码兼容。对于double abs(double)
这不是问题,因为该函数不存在于 C 头文件中。来自 cppreference:
这甚至适用于不属于 C 标准库的函数和函数重载。这意味着:在全局命名空间中也允许有 double abs(double) ,但这不是必需的。
cstdlib
is the C++ version of the C headerstdlib.h
. Such headers must introduce the names in thestd
namespace and they are allowed to introcude them in the global namespace. There is nodouble abs(double)
in the C header, hence there is no reason to introduce it in the global namespace like it is done for the C variants of the funciton. Note that C has no namespaces, and having the function in the global namespace helps for compatibility with C code. Fordouble abs(double)
this is not an issue, because the function does not exist in the C header.From cppreference:
This applies even to functions and function overloads that are not part of C standard library. That means: It would be allowed to have
double abs(double)
in the global namespace too, but it is not required.因为C++标准允许将其导入到全局命名空间中。
因为C++标准并不要求将其导入到全局命名空间中。
相关标准报价:
显然,您使用的 C++ 标准库实现选择使用 C 标准库函数引用规则的最后一段中描述的策略,而选择不使用 C++ 标准库重载的该策略。标准不保证这个特定结果,但它是符合要求的。
另一种可能的结果是
abs(0.1)
由于使用未声明的标识符而失败。您不能依赖在全局命名空间中声明的 C++ 标准库名称(除非您使用已弃用的
C 标准标头)。Because the C++ standard allows it to be imported into the global namespace.
Because the C++ standard doesn't require it to be imported into the global namespace.
Relevant standard quotes:
Evidently, the C++ standard library implementation that you use had chosen to use the strategy described in the last paragraph of the quoted rule for the C standard library function, while having chosen not to use that strategy for the C++ standard library overloads. This specific outcome isn't guaranteed by the standard but it is conforming.
Another possible outcome would be that
abs(0.1)
would fail as use of an undeclared identifier. You cannot rely on C++ standard library names to be declared in the global namespace (unless you use the deprecated<name.h>
C standard headers).