gcc의 모호한 연산자


13

일부 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<<line에 대한 모호한 오류가 발생합니다 os << elem << " ". 그리고이 오류조차도 플래그 -std=c++17또는로 컴파일 할 때만 나타납니다 -std=c++2a.

이 오류에 대한 합리적인 것 같다 std::string컴파일러는 기존의 함수 템플릿을 감지하기 때문에, 그 세계에 대한 operator<<출력 스트림과를 받아 그 basic_string<CharT, Traits, Allocator>으로, Allocator형의 존재가 기본값 std::allocator.

내 질문은 왜 적어도 3 개의 컴파일러가 컴파일하고 다른 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

필수 godbolt 링크 : https://godbolt.org/z/R_aSKR

답변:


8

이 오류에 대한 합리적인 것 같다 std::string컴파일러는 기존의 함수 템플릿을 감지하기 때문에, 그 세계에 대한 operator<<출력 스트림과를 받아 그 basic_string<CharT, Traits, Allocator>으로, Allocator형의 존재가 기본값 std::allocator.

C ++ 17의 새로운 기능인 P0522 에서 나온C<T, A> 것과 유사한 형식과 같은 매개 변수를 일치시키는 기능 입니다. 이 문서를 작성하기 전에 운영자는 후보자로 간주되지 않습니다.basic_string<CharT, Traits, Allocator=std::allocator<CharT>>

그러나 clang은 의도적으로이 기능을 기본적으로 구현하지 않기로 선택합니다. 에서 자신의 상태 :

결함 보고서의 해결에도 불구하고이 기능은 모든 언어 버전에서 기본적으로 비활성화되어 -frelaxed-template-template-args있으며 Clang 4 이상의 플래그 를 사용하여 명시 적으로 활성화 할 수 있습니다 . 표준 변경시 템플릿 부분 순서에 대한 해당 변경이 없으므로 합리적이고 이전에 유효했던 코드에 대한 모호성 오류가 발생합니다. 이 문제는 곧 해결 될 예정입니다.

해당 플래그를 추가하면 코드가 모호해진다는 것을 알 수 있습니다. 귀하의 예는 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도 같은 선택을 할 수 있지만 모르겠습니다. 표준에 대한 정답은 전화가 모호하다는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.