我制作了一个用于打印一些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;
}
这可以在MSVC,Clang和ICC上按预期方式进行编译和工作,但是在使用GCC(trunk)进行编译时,会给operator<<
该行带来大量错误os << elem << " "
。并且甚至仅当使用标志-std=c++17
或进行编译时,才会出现此错误-std=c++2a
。
对于该错误似乎是合理的std::string
,因为编译器检测到现有的函数模板,该模板对于global operator<<
接受输出流和a basic_string<CharT, Traits, Allocator>
,其Allocator
类型默认为std::allocator
。
我的问题是,为什么从我的理解(至少是Clang)开始,它为什么可以与其他3个编译器一起编译并与之一起工作,所以在Linux上使用与gcc相同的标准库实现,因此它具有相同的功能模板。 operator<<
报告的错误是
error: ambiguous overload for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'const std::__cxx11::basic_string<char>')
和两个候选人
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>]'
GCC,Clang和ICC的编译器参数
-std=c++2a -O3 -Wall -Wextra -Wpedantic -Werror
对于MSVC
/std:c++latest /O2 /W3
强制性Godbolt链接:https ://godbolt.org/z/R_aSKR