2012-01-29 11 views
12

오늘은 C 스타일 배열에 대한 operator<<에 과부하를 위해 좋은 생각이 될 것이라고 생각 : 오버로드 연산자 << 배열에 대한

template<typename T, size_t N> 
std::ostream& operator<<(std::ostream& os, T(&a)[N]) 
{ 
    os << '{' << a[0]; 
    for (size_t i = 1; i < N; ++i) 
    { 
     os << ',' << ' ' << a[i]; 
    } 
    os << '}'; 
    return os; 
} 

int main() 
{ 
    int numbers[] = {2, 3, 5, 7, 11, 13, 17, 19}; 
    std::cout << numbers << '\n'; 
} 

는 사실이 멋지게 {2, 3, 5, 7, 11, 13, 17, 19}를 인쇄합니다. 그러나 오버로드를 제공함으로써 더 이상 문자열 리터럴을 인쇄 할 수 없습니다.

std::cout << "hello world\n"; 

error: ambiguous overload for 'operator<<' in 'std::cout << "hello world\012"' 
note: candidates are: 

note: std::basic_ostream<_CharT, _Traits>::__ostream_type& 
std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _ 
Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_ 
type = std::basic_ostream<char>] <near match> 

note: no known conversion for argument 1 from 'const char [13]' to 'long int' 

이것은 정말로 수수께끼입니다. 왜 컴파일러는 const char[13]에서 long int으로의 변환이 처음에 없으면 long int 과부하를 고려합니까? 이 오류 메시지의

변화는 long unsigned int, short int, short unsigned int, int, unsigned int, long long intlong long unsigned int을 위해 나타납니다.

(다른 후보 const void*, const char*const _CharT*, 내 자신의 템플릿입니다.) 난 단지가 아닌 문자 유형에 대한 템플릿을 제공하여 문제를 해결


:

template<typename T, size_t N> 
typename std::enable_if< 
    !std::is_same<typename std::remove_cv<T>::type, char>::value, 
std::ostream&>::type operator<<(std::ostream& os, T(&a)[N]) 

하지만를 나는 왜 컴파일러가 수치 형을 후보로 생각하는지에 대한 질문에 당황 스럽다.

답변

3

과부하 해결의 첫 번째 단계는 제공된 인수의 개수를 허용 할 수있는 실행 가능 함수를 식별하는 것입니다 (유형을 완전히 무시 함). (예 : 13.3.2 [over.match.viable] 참조).

그런 다음 필요한 최적의 실행 가능 기능을 결정하기 위해 필요한 변환이 고려됩니다.

이 경우 고유 한 최고점은 없습니다 (두 개의 똑같이 좋은 후보자가 있습니다).

오류 메시지는 단지 두 모호한 경우를 알 수 있습니다. 그러나 나는 다른 모든 실용적인 기능이 사라진 이유를 보여주는 도움을주기 위해 노력하고 있다고 생각합니다. 때로는 호출하려는 함수가 고려되지 않은 이유를 알 수 없을 때 유용합니다.

하지만 대부분은 과부하가 많은 operator << 또는 operator >> (또는 심지어 operator [])과 같은 기능에 대해서는 잡음이 많은 것에 동의합니다.

1

컴파일러는 프로그램을 거부해야합니다. 난 열쇠가 당신의 과부하와 ostream::operator<<(char const *) 모두 오류 메시지에 나타납니다라고 생각합니다. 완전한 것들은 아마도 빨간 청어입니다. reinterpret_castlong int (§5.2.10/4)에 대한 포인터 (또는 문자열 리터럴)가 될 수 있지만, 확실히 표준 변환은 아닙니다. 아마 컴파일러는 당신에게 더 많은 과부하를줌으로써 도움이 될뿐입니다.

과부하와 ostream 구성원이 주어지면 과부하 해결은 우선 순위 규칙이 없기 때문에 실패합니다 (§13.3.1.2). 따라서 구성원 부하가 char const *과 충돌 할 수있는 유일한 경우이므로 수정 프로그램이 적절한 것으로 보입니다.

+0

'std :: ostream'은 클래스에 대한 참조입니다. – Mankarse