std :: transform () 및 toupper (), 일치하는 함수 없음
이 질문에서 코드를 시도했습니다 C ++ std :: transform () 및 toupper () .. 왜 이것이 실패합니까?
#include <iostream>
#include <algorithm>
int main() {
std::string s="hello";
std::string out;
std::transform(s.begin(), s.end(), std::back_inserter(out), std::toupper);
std::cout << "hello in upper case: " << out << std::endl;
}
이론적으로는 Josuttis의 책에있는 예제 중 하나이므로 작동 했어야하지만 http://ideone.com/aYnfv 컴파일하지는 않습니다 .
GCC가 불만을 제기 한 이유 :
no matching function for call to ‘transform(
__gnu_cxx::__normal_iterator<char*, std::basic_string
<char, std::char_traits<char>, std::allocator<char> > >,
__gnu_cxx::__normal_iterator<char*, std::basic_string
<char, std::char_traits<char>, std::allocator<char> > >,
std::back_insert_iterator<std::basic_string
<char, std::char_traits<char>, std::allocator<char> > >,
<unresolved overloaded function type>)’
여기에 뭔가 빠졌나요? GCC 관련 문제입니까?
::toupper
대신 사용하십시오 std::toupper
. 즉, toupper
네임 스페이스에 정의 된 것이 아니라 전역 네임 스페이스에 정의됩니다 std
.
std::transform(s.begin(), s.end(), std::back_inserter(out), ::toupper);
코드가 작동하지 않는 이유 : toupper
이름 std
을 확인할 때 문제를 일으키는 네임 스페이스에 또 다른 오버로드 된 함수 가 있습니다. 컴파일러는 단순히 std::toupper
. 이것이 컴파일러가 unresolved overloaded function type
오류 메시지에서 오버로드가 있음을 나타내는 이유 입니다.
따라서 컴파일러가 올바른 오버로드를 해결하는 데 도움이되도록 다음 std::toupper
과 같이 캐스팅 해야합니다.
(int (*)(int))std::toupper
즉, 다음이 작동합니다.
//see the last argument, how it is casted to appropriate type
std::transform(s.begin(), s.end(), std::back_inserter(out),(int (*)(int))std::toupper);
직접 확인해보세요 : http://ideone.com/8A6iV
문제
std::transform(
s.begin(),
s.end(),
std::back_inserter(out),
std::toupper
);
'
transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::back_insert_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)
'에 대한 호출과 일치하는 함수가 없습니다.
이것은 잘못된 오류입니다. 흥미로운 부분은 호출에 대해 "일치하는 함수가 없음"이 아니라 일치하는 함수가없는 이유 입니다.
그 이유 는 " <unresolved overloaded function type>
" 의 함수 참조를 인수로 전달하고 GCC는이 오버로드 해결 실패보다는 호출에서 오류를 선호하기 때문입니다.
설명
먼저 C ++에서 C 라이브러리가 상속되는 방식을 고려해야합니다. <ctype.h>
기능이 int toupper(int)
있습니다.
C ++는 다음을 상속합니다.
[n3290: 21.7/1]:
표 74, 75, 76, 77, 78, 79가 설명하는 헤더를<cctype>
,<cwctype>
,<cstring>
,<cwchar>
,<cstdlib>
(문자 변환)하고<cuchar>
, 각각.
[n3290: 21.7/2]:
이 헤더의 내용은 C 표준 라이브러리 헤더와 동일하게한다<ctype.h>
,<wctype.h>
,<string.h>
,<wchar.h>
, 및<stdlib.h>
상기 C 유니 TR 헤더<uchar.h>
각각 [...]
[n3290: 17.6.1.2/6]:
C에서 함수로 정의 된 이름은 C ++ 표준 라이브러리에서 함수로 정의되어야합니다.
그러나 using <ctype.h>
은 더 이상 사용되지 않습니다.
[n3290: C.3.1/1]:
표준 C 라이브러리와의 호환성을 위해 C ++ 표준 라이브러리는 18 개의 C 헤더 (D.5)를 제공하지만 C ++에서는 더 이상 사용되지 않습니다.
C에 액세스하는 방법 toupper
은 C ++ 이전 버전과의 호환성 헤더를 사용하는 것 <cctype>
입니다. 이러한 헤더의 경우 콘텐츠가 네임 스페이스 로 이동되거나 복사됩니다 (구현에 따라 다름) std
.
[n3290: 17.6.1.2/4]:
[..] 그러나 C ++ 표준 라이브러리에서 선언 (C에서 매크로로 정의 된 이름 제외)은 네임 스페이스 std의 네임 스페이스 범위 (3.3.6) 내에 있습니다. 이러한 이름이 전역 네임 스페이스 범위 내에서 처음 선언 된 다음 명시 적 using-declarations (7.3.3)에 의해 네임 스페이스 std에 삽입되는지 여부는 지정되지 않습니다 .
그러나 C ++ 라이브러리는 헤더에 새로운 로케일 고유의 기능 템플릿 소개 <locale>
것, 또한 전화 toupper
(네임 스페이스에, 물론을 std
) :
[n3290: 22.2]:
[..]template <class charT> charT toupper(charT c, const locale& loc);
[..]
따라서를 사용할 때 선택할 수 std::toupper
있는 두 가지 과부하가 있습니다. 어떤 기능을 사용하고 싶은지 GCC에 알려주지 않았기 때문에 과부하를 해결할 std::transform
수없고 호출을 완료 할 수 없습니다.
Disparity
Now, the OP of that original question did not run into this problem. He likely did not have the locale version of std::toupper
in scope, but then again you didn't #include <locale>
either!
However:
[n3290: 17.6.5.2]:
A C++ header may include other C++ headers.
So it just so happens that either your <iostream>
or your <algorithm>
, or headers that those headers include, or headers that those headers include (etc), lead to the inclusion of <locale>
on your implementation.
Solution
There are two workarounds to this.
You may provide a conversion clause to coerce the function pointer into referring to the overload that you wish to use:
std::transform( s.begin(), s.end(), std::back_inserter(out), (int (*)(int))std::toupper // specific overload requested );
You may remove the locale version from the overload set by explicitly using the global
toupper
:std::transform( s.begin(), s.end(), std::back_inserter(out), ::toupper // global scope );
However, recall that whether or not this function in
<cctype>
is available is unspecified ([17.6.1.2/4]
), and using<ctype.h>
is deprecated ([C.3.1/1]
).Thus, this is not the option that I would recommend.
(Note: I despise writing angle brackets as if they were part of header names — they are part of #include
syntax, not header names — but I've done it here for consistency with the FDIS quotes; and, to be honest, it is clearer...)
ReferenceURL : https://stackoverflow.com/questions/7131858/stdtransform-and-toupper-no-matching-function
'IT TIP' 카테고리의 다른 글
스레드가 자체적으로 교착 상태가 될 수 있습니까? (0) | 2020.12.29 |
---|---|
Android에서 전역 예외 처리 사용 (0) | 2020.12.29 |
jQuery Deferred-여러 AJAX 요청이 완료되기를 기다리는 중 (0) | 2020.12.28 |
루프의 파이썬 목록에서 항목을 제거하는 방법은 무엇입니까? (0) | 2020.12.28 |
TFS에서 특정 사용자의 체크인 기록을 보는 방법은 무엇입니까? (0) | 2020.12.28 |