gpt4 book ai didi

c++ - gcc中的二义性运算符

转载 作者:行者123 更新时间:2023-12-03 23:52:58 25 4
gpt4 key购买 nike

我做了一个用于打印一些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 ,因为编译器检测到全局 operator<< 的现有函数模板接受一个输出流和一个 basic_string<CharT, Traits, Allocator> , 与 Allocator类型默认为 std::allocator .

我的问题是为什么它可以编译并与其他 3 个编译器一起工作,据我所知,Clang 至少在 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

强制神箭链接: https://godbolt.org/z/R_aSKR

最佳答案

The error seems reasonable, for std::string, since compiler detects an existing function template that for global operator<< that accepts an output stream and a basic_string<CharT, Traits, Allocator>, with the Allocator type being defaulted to std::allocator.



这种匹配参数的能力,如 C<T, A>到类似 basic_string<CharT, Traits, Allocator=std::allocator<CharT>> 的类型在 C++17 中是新的,它来自 P0522 .在该论文之前,您的运算符(operator)不会被视为候选人。

但是,clang 故意选择默认不实现此功能。来自 their status :

Despite being the resolution to a Defect Report, this feature is disabled by default in all language versions, and can be enabled explicitly with the flag -frelaxed-template-template-args in Clang 4 onwards. The change to the standard lacks a corresponding change for template partial ordering, resulting in ambiguity errors for reasonable and previously-valid code. This issue is expected to be rectified soon.



您可以看到,当您添加该标志时,您的代码在 clang 上也变得模棱两可。您的示例是 clang 在这里保护的那种合理且以前有效的代码。我见过的一个类似的例子:
template <class T> struct some_trait;

template <template <class> class C, class A>
struct some_trait<C<A>> { /* ... */ };

template <template <class> class C, class A, class B>
struct some_trait<C<A, B>> { /* ... */ };
some_trait<vector<int>>过去没问题(使用二进制版本),但现在变得模棱两可(在一元和二进制版本之间)。

MSVC 可能会做出同样的选择,但我不知道。根据标准,正确答案是调用不明确。

关于c++ - gcc中的二义性运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58218339/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com