2012-01-29 35 views
12

Hôm nay tôi nghĩ rằng nó sẽ là một ý tưởng tốt đẹp để quá tải operator<< cho mảng C phong cách:điều hành quá tải << cho mảng

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'; 
} 

Thật vậy, đây in {2, 3, 5, 7, 11, 13, 17, 19} độc đáo. Tuy nhiên, bằng cách cung cấp tình trạng quá tải đó, tôi không thể in các chuỗi chữ nữa:

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' 

Điều này thực sự khó hiểu. Tại sao trình biên dịch thậm chí còn xem xét quá tải long int khi không có chuyển đổi từ const char[13] thành long int ngay từ đầu?

Các biến thể của thông báo lỗi này xuất hiện cho long unsigned int, short int, short unsigned int, int, unsigned int, long long intlong long unsigned int.

(ứng cử viên khác là const void*, const char*const _CharT*, và mẫu của riêng tôi.)


tôi giải quyết vấn đề bằng cách cung cấp các khuôn mẫu để chỉ các loại phi char:

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]) 

Nhưng Tôi vẫn còn bối rối bởi câu hỏi tại sao trình biên dịch coi các kiểu số như ứng cử viên.

Trả lời

3

Giai đoạn đầu tiên của độ phân giải quá tải là xác định các hàm khả thi, là những hàm có thể chấp nhận số lượng đối số được cung cấp (loại bỏ hoàn toàn các loại). (Xem ví dụ 13.3.2 [over.match.viable]).

Sau đó, bất kỳ chuyển đổi cần thiết nào đều được xem xét để xác định đó là hàm khả thi tốt nhất duy nhất.

Trong trường hợp này, không có trường hợp nào tốt nhất như vậy (có hai ứng cử viên tốt như nhau).

Thông báo lỗi chỉ có thể cho bạn biết hai trường hợp không rõ ràng. Nhưng tôi nghĩ rằng họ đang cố gắng để giúp đỡ bằng cách hiển thị lý do tại sao tất cả các chức năng khả thi khác bị mất. Đôi khi điều này rất hữu ích, khi bạn không thể tìm ra lý do tại sao hàm bạn muốn được gọi chưa được xem xét.

Nhưng tôi đồng ý rằng hầu hết nó chỉ là rất nhiều tiếng ồn, đặc biệt là đối với các chức năng như operator << hoặc operator >> (hoặc thậm chí operator []) có quá nhiều tình trạng quá tải.

1

Trình biên dịch là chính xác để từ chối chương trình. Tôi nghĩ điều quan trọng là quá tải của bạn và ostream::operator<<(char const *) đều xuất hiện trong thông báo lỗi. Những cái tách rời có lẽ là một cá trích đỏ… bạn có thể reinterpret_cast một con trỏ (hoặc một chuỗi ký tự) đến long int (§5.2.10/4), nhưng đó chắc chắn không phải là một chuyển đổi tiêu chuẩn. Có lẽ trình biên dịch chỉ cố gắng hữu ích bằng cách cho bạn nhiều tình trạng quá tải.

Với tình trạng quá tải và thành viên ostream, độ phân giải quá tải không thành công vì không có quy tắc ưu tiên để quyết định giữa chúng (§13.3.1.2). Vì vậy, vì quá tải thành viên char const * là quá trình duy nhất bạn có thể xung đột, sửa lỗi của bạn có vẻ phù hợp.

+0

'std :: ostream' là tham chiếu đến một lớp học. – Mankarse

Các vấn đề liên quan