선언이 std 네임 스페이스에 영향을 미칠 수 있습니까?
#include <iostream>
#include <cmath>
/* Intentionally incorrect abs() which seems to override std::abs() */
int abs(int a) {
return a > 0? -a : a;
}
int main() {
int a = abs(-5);
int b = std::abs(-5);
std::cout<< a << std::endl << b << std::endl;
return 0;
}
출력이 -5
and 가 될 것으로 예상 5
했지만 출력은 -5
and -5
입니다.
이 사건이 왜 일어날 지 궁금합니다.
사용과 관련이 std
있습니까?
언어 사양을 사용하면 전역 네임 스페이스 <cmath>
에서 표준 함수를 선언 (및 정의) 한 다음 using-declarations를 통해 네임 스페이스로 가져옴으로써 구현을 구현할 수 있습니다 . 이 접근법이 사용되는지 여부는 지정되지 않았습니다.std
20.5.1.2 헤더
4 [...] 그러나 C ++ 표준 라이브러리에서 선언 (C에서 매크로로 정의 된 이름 제외)은 네임 스페이스의 네임 스페이스 범위 (6.3.6) 내에 있습니다std
. 이러한 이름 (21 ~ 33 절 및 부록 D에 추가 된 오버로드 포함)이 먼저 전역 네임 스페이스 범위 내에서 선언 된 다음std
명시 적 using-declarations (10.3.3)에 의해 네임 스페이스 에 삽입되는지 여부는 지정되지 않습니다 .
분명히이 접근법을 따르기로 결정한 구현 중 하나 (예 : GCC)를 다루고 있습니다. 즉, 구현은을 제공 ::abs
하지만 std::abs
단순히를 "참조"합니다 ::abs
.
이 경우에 남아있는 한 가지 질문은 표준에 추가 ::abs
하여 자신의을 선언 할 수 있었던 ::abs
이유, 즉 다중 정의 오류가없는 이유입니다. 이는 일부 구현 (예 : GCC)에서 제공하는 다른 기능으로 인해 발생할 수 있습니다. 표준 기능을 소위 약한 기호 로 선언 하여 사용자 정의로 "대체"할 수 있습니다.
이 두 가지 요소가 함께 관찰 된 효과를 생성합니다. 약한 기호 ::abs
를 대체하면 std::abs
. 이것이 언어 표준에 얼마나 잘 부합하는지는 다른 이야기입니다 ... 어쨌든이 행동에 의존하지 마십시오. 언어에 의해 보장되지 않습니다.
GCC에서이 동작은 다음과 같은 최소한의 예제로 재현 할 수 있습니다. 하나의 소스 파일
#include <iostream>
void foo() __attribute__((weak));
void foo() { std::cout << "Hello!" << std::endl; }
다른 소스 파일
#include <iostream>
void foo();
namespace N { using ::foo; }
void foo() { std::cout << "Goodbye!" << std::endl; }
int main()
{
foo();
N::foo();
}
In this case you will also observe that the new definition of ::foo
("Goodbye!"
) in the second source file also affects the behavior of N::foo
. Both calls will output "Goodbye!"
. And if you remove the definition of ::foo
from the second source file, both calls will dispatch to the "original" definition of ::foo
and output "Hello!"
.
The permission given by the above 20.5.1.2/4 is there to simplify implementation of <cmath>
. Implementations are allowed to simply include C-style <math.h>
, then redeclare the functions in std
and add some C++-specific additions and tweaks. If the above explanation properly describes the inner mechanics of the issue, then a major part of it depends on replaceability of weak symbols for C-style versions of the functions.
Note that if we simply globally replace int
with double
in the above program, the code (under GCC) will behave "as expected" - it will output -5 5
. This happens because C standard library does not have abs(double)
function. By declaring our own abs(double)
, we do not replace anything.
But if after switching from int
with double
we also switch from abs
to fabs
, the original weird behavior will reappear in its full glory (output -5 -5
).
This is consistent with the above explanation.
Your code causes undefined behaviour.
C++17 [extern.names]/4:
Each function signature from the C standard library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
So you cannot make a function with the same prototype as the Standard C library function int abs(int);
. Regardless of which headers you actually include or whether those headers also put C library names into the global namespace.
However, it would be allowed to overload abs
if you provide different parameter types.
참고URL : https://stackoverflow.com/questions/50898508/can-a-declaration-affect-the-std-namespace
'programing tip' 카테고리의 다른 글
다른 CSS 규칙 내에서 하나의 CSS 규칙을 참조 할 수 있습니까? (0) | 2020.08.29 |
---|---|
Eclipse, ADT 22.6에서 AVD (Android Virtual Devices)를 만들거나 편집 할 수 없습니다. (0) | 2020.08.29 |
JAR 내에 네이티브 라이브러리와 JNI 라이브러리를 번들링하는 방법은 무엇입니까? (0) | 2020.08.29 |
IIS 풀의 LoadUserProfile을 설정하면 정확히 어떻게됩니까? (0) | 2020.08.29 |
AngularJS 지시문에서 속성 액세스 (0) | 2020.08.29 |