Nhớ lại rằng std::string
không phải là một loại độc lập, nó thực sự là một chuyên môn mẫu lớp - std::basic_string<char>
. Các chi tiết rất quan trọng là sự quá tải khả năng trình chiếu một std::string
không mất một cuộc tranh luận std::string const&
, nó là một function template rằng suy luận một std::basic_string const&
:
template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const std::basic_string<CharT, Traits, Allocator>& str);
Template trích không bao giờ xem xét chuyển đổi. Tra cứu tên sẽ tìm thấy mẫu chức năng này, và sau đó loại bỏ tại như là không khả thi do thất bại khấu trừ. S
không phải là basic_string<CharT, Traits, Allocator>
cho bất kỳ loại nào như vậy, vì vậy chúng tôi đã hoàn tất. Các nhà khai thác luồng khả thi duy nhất sẽ là tất cả những cái tích phân, trong đó bool
là kết quả phù hợp nhất.
Nếu có đặc biệt là một chức năng với chữ ký:
std::ostream& operator<<(std::ostream&, std::string const&);
Sau đó cuộc gọi sẽ là mơ hồ - bạn sẽ nhận được hai chuyển đổi người dùng xác định đó sẽ được xếp hạng tương đương.
này rất dễ dàng để xác minh bằng cách sử dụng các chức năng của chúng ta thay vì triệu quá tải cho operator<<
:
void foo(bool); // #1
void foo(std::string); // #2
void bar(bool); // #3
template <class C, class T, class A>
void bar(std::basic_string<C,T,A>); // #4
foo(S{}); // error: ambiguous
bar(S{}); // calls #3
Chỉ cần để nitpick, không có gì là bao giờ ngầm đúc.Các loại được chuyển đổi hoàn toàn, nhưng * cast * có nghĩa là * chuyển đổi rõ ràng *. – StoryTeller
@StoryTeller Cảm ơn, rất tốt để biết thuật ngữ cụ thể. Tôi đã chỉnh sửa câu hỏi của mình. – YSC