Clang은 코드를 컴파일하지 않지만 gcc 및 msvc는 코드를 컴파일했습니다.


14

내 코드 또는 컴파일러 (가능하지 않은)에서 문제가 무엇인지 이해하지 못합니다. 다음과 같은 코드가 있습니다.

#include <iostream>
#include <type_traits>
#include <set>


template<typename T, typename = void>
struct TestA: std::false_type {};

template<typename T>
struct TestA<T, std::void_t<typename T::reverse_iterator>> : std::true_type {};

template<typename T>
struct TestA<T, std::void_t<typename T::dummy_iterator>> : std::true_type {};

int main()
{
    std::cout << TestA<std::set<int>>::value;
}

GCC와 MSVC 모두 컴파일합니다. 다른 버전의 GCC와 MSVC 17 (local) 및 19를 사용하여 godbolt에서 테스트했습니다. 다음 링크는 https://godbolt.org/z/Enfm6L 입니다.

그러나 Clang은 컴파일하지 않고 오류를 발생시킵니다.

redefinition of `'TestA<T, std::void_t<typename T::dummy_iterator> >'`

그리고 관심이 있습니다.이 코드 조각이 틀리거나 다른 것이 표준의 일부일 수 있습니다.


어떻게하다 "표준 : 세트 :: reverse_iterator""표준 : : 설정 : dummy_iterator" 그 소리 헤더에 정의?
mvidelgauz

std :: set :: dummy_iterator는 clang 헤더에 전혀 정의되어 있지 않습니다 (희망합니다). dummy_iterator를 원하는대로 변경할 수 있으며 아래에 표시된 것처럼 문제가 정의에 없으므로 결과가 변경되지 않습니다.
Andrei

감사합니다 Andrei, 나는 답변을 읽고 정말 흥미 롭습니다
mvidelgauz

답변:


9

이것은 CWG 1558 과 관련이 있습니다.

별명 템플리트 전문화에서 사용되지 않은 인수 처리는 현재 17.6.7 [temp.alias]로 지정되지 않습니다. 예를 들면 다음과 같습니다.

  #include <iostream>

  template <class T, class...>
    using first_of = T;

  template <class T>
    first_of<void, typename T::type> f(int)
      { std::cout << "1\n"; }

  template <class T>
    void f(...)
      { std::cout << "2\n"; }

  struct X { typedef void type; };

  int main() {
    f<X>(0);
    f<int>(0);
  }

first_of에 대한 참조가 T와 int가 단순히 void와 같거나 대체 실패입니까?

이 문제는 해결 된 이후의 결함이지만, 사용한 Clang 버전이 아직 수정 사항을 구현하지 않은 경우에도 두 번째 인수를 단순히로 정의 void하고 전체 대체 실패를 수행하지 않는 것으로 두 전문화를 여전히 고려할 수 있습니다 . 해결 방법은 일반 별칭을 사용하지 std::void_t않고 약간 더 복잡한 버전을 사용하는 것입니다.

template <typename...> struct voider { using type = void; };
template <typename... T> using my_void_t = typename voider<T...>::type;

별명을 나타내는 클래스 템플릿의 경우 대체 실패가 정의됩니다. 예제에 연결하면 Clang https://godbolt.org/z/VnkwsM이 완화 됩니다 .


1
또 다른 해결 방법은 각 요구 사항에 대한 특성을 만든 다음 (또는 enable_ifstd::disjunction
require

도움과 참조 감사합니다! Clang에서 이런 종류의 버그에 대해 듣고 슬프다. 웃긴, void_t 구현이 표준이라고 생각했습니다. 템플릿 별칭 지정 아이디어를 채택 할 수 없습니다.
Andrei
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.