포인터 붕괴가 템플릿 추론보다 우선합니다
문자열에서 작동하는 코드를 작성할 때 오버로드를 시도하는 딜레마에 직면하는 것이 일반적입니다. 배열 기반 및 비배열 기반 문자열 표현을 모두 수용하는 함수는 예상치 못한 결과를 초래할 수 있습니다. 동작.
이 특정 시나리오에서 초기 함수 foo는 문자 배열의 길이를 인쇄하도록 정의됩니다.
template <size_t N> void foo(const char (&s)[N]) { std::cout << "array, size=" << N-1 << std::endl; }
이 함수는 문자 배열을 허용합니다. 배열 길이를 출력합니다. 그러나 foo를 확장하여 배열이 아닌 문자열도 처리하면 모호성이 발생합니다.
void foo(const char* s) { std::cout << "raw, size=" << strlen(s) << std::endl; }
두 번째 foo 오버로드는 배열이 아닌 문자열을 처리하기 위한 것입니다. 하지만 놀랍게도 이 확장으로 인해 배열과 비배열 모두에 대해 원래 오버로드가 우회됩니다. strings:
foo("hello") // prints raw, size=5
이 예상치 못한 동작은 포인터 붕괴 개념에서 비롯됩니다. 배열은 본질적으로 첫 번째 요소에 대한 포인터이며 배열을 포인터로 변환하는 것은 매우 저렴한 작업입니다. 결과적으로 컴파일러는 배열 인수로부터 암시적 변환이 필요하더라도 포인터 매개 변수를 허용하는 오버로드의 우선 순위를 지정합니다.
배열 기반 오버로드가 배열에 사용되는 경우 원하는 동작을 보장하려면, 추가 오버로드를 도입해야 합니다.
template <typename T> auto foo(T s) -> std::enable_if_t<std::is_convertible<T, char const*>{}> { std::cout << "raw, size=" << std::strlen(s) << std::endl; }
이 오버로드는 템플릿 추론을 사용하고 문자 포인터로 변환할 수 있는 유형으로 적용을 제한합니다. 부분 순서 지정을 통해 이제 컴파일러는 인수 유형에 따라 적절한 foo 함수를 올바르게 선택합니다.
위 내용은 C 함수 오버로딩에서 포인터 붕괴가 템플릿 추론을 재정의하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!