Tôi đã tạo một mẫu hàm để in một số thùng chứa stl
#include <iostream>
#include <vector>
#include <string>
template <template <typename, typename> class C, typename T, typename A>
std::ostream& operator<<(std::ostream& os, const C<T, A>& container)
{
for (auto& elem : container)
{
os << elem << " ";
}
return os;
}
int main()
{
std::vector<std::string> v { "One", "Two", "Three" };
std::cout << v << std::endl;
return 0;
}
Điều này biên dịch và hoạt động như mong đợi trên MSVC, Clang và ICC, nhưng khi biên dịch với GCC (trung kế), nó sẽ operator<<
gây ra lỗi không rõ ràng cho dòng os << elem << " "
. Và thậm chí lỗi này chỉ xuất hiện khi biên dịch với cờ -std=c++17
hoặc -std=c++2a
.
Lỗi có vẻ hợp lý, vì std::string
, trình biên dịch phát hiện một mẫu hàm hiện có cho toàn cầu operator<<
chấp nhận luồng đầu ra và a basic_string<CharT, Traits, Allocator>
, với Allocator
kiểu được mặc định std::allocator
.
Câu hỏi của tôi là tại sao nó biên dịch và làm việc với 3 trình biên dịch khác, theo hiểu biết của tôi, Clang ít nhất, sử dụng cùng một triển khai thư viện tiêu chuẩn trên linux như gcc, vì vậy nó có cùng một khuôn mẫu hàm cho operator<<
Lỗi được báo cáo là
error: ambiguous overload for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'const std::__cxx11::basic_string<char>')
Và hai ứng cử viên
note: candidate: 'std::ostream& operator<<(std::ostream&, const C<T, A>&) [with C = std::__cxx11::basic_string; T = char; A = std::char_traits<char>; std::ostream = std::basic_ostream<char>]'
note: candidate: 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::__cxx11::basic_string<_CharT, _Traits, _Allocator>&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'
Trình biên dịch đối số cho GCC, Clang và ICC
-std=c++2a -O3 -Wall -Wextra -Wpedantic -Werror
An cho MSVC
/std:c++latest /O2 /W3
Liên kết Godbolt bắt buộc: https://godbolt.org/z/R_aSKR