내 코드 또는 컴파일러 (가능하지 않은)에서 문제가 무엇인지 이해하지 못합니다. 다음과 같은 코드가 있습니다.
#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> >'`
그리고 관심이 있습니다.이 코드 조각이 틀리거나 다른 것이 표준의 일부일 수 있습니다.
답변
이것은 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이 완화 됩니다 .