2017-04-08 7 views
0

템플릿 부분 특수화가 보이지 않게되는 이유를 이해하려고합니다.C++ 14 템플릿 부분 특수화가 표시되지 않습니다.

나는 아래 오류에 어떻게 도달했는지에 대한 작은 예제를 수행 중입니다. 이 예에서는 operator<<을 오버로드하여 ostreams에 인쇄하려고 시도합니다. 튜플 인쇄에는 1이라는 질문에서 작동하는 솔루션이 있습니다. 내 질문은 왜 보이지 않는 오류와 함께 실패 하나에 관한 것입니다.

그 소리에서 전체 오류 :

call to function 'operator<<' that is neither visible in the template definition nor found by argument-dependent 
     lookup 
     operator<<(os, std::get<0>(t)); 
     ^
testing.cpp:9:47: note: in instantiation of member function 'tuple_printer<1, std::__1::tuple<std::__1::tuple<const char *, int> > >::print' 
     requested here 
     tuple_printer<s-1, std::tuple<T...>>::print(os, t); 
              ^
testing.cpp:33:52: note: in instantiation of member function 'tuple_printer<2, std::__1::tuple<const char *, int> >::print' requested here 
    tuple_printer<sizeof...(T), std::tuple<T...>>::print(os, t); 
               ^
testing.cpp:40:15: note: in instantiation of function template specialization 'operator<<<const char *, int>' requested here 
    std::cout << std::make_tuple("hello", 5) << std::endl; 
      ^
testing.cpp:30:15: note: 'operator<<' should be declared prior to the call site 
std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& t) 

예제 코드 :

#include <tuple> 
#include <iostream> 

template<size_t s, typename... T> 
struct tuple_printer{ 
    static void print(std::ostream& os, const std::tuple<T...>& t){ 
     os << ", "; 
     os << std::get<s-1>(t); 
     tuple_printer<s-1, std::tuple<T...>>::print(os, t); 
    } 
}; 

template<typename... T> 
struct tuple_printer<0, T...>{ 
    static void print(std::ostream& os, const std::tuple<T...>& t){ 
     //nothing to do here 
    } 
}; 

template<typename... T> 
struct tuple_printer<1, T...>{ 
    static void print(std::ostream& os, const std::tuple<T...>& t){ 
     //no need for comma separator 
     os << std::get<0>(t); 
    } 
}; 

template <typename... T> 
std::ostream& operator<<(std::ostream& os, const std::tuple<T...>& t) 
{ 
    os << "["; 
    tuple_printer<sizeof...(T), std::tuple<T...>>::print(os, t); 
    return os << "]"; 
} 

int main() 
{ 
    std::cout << std::make_tuple(2, 3.14159F, 2345.678) << std::endl; 
    std::cout << std::make_tuple("hello", 5) << std::endl; 
    std::cout << std::make_tuple() << std::endl; 
    return 0; 
} 
+0

질문에 관련되지 않음,하지만 난'템플릿 <유형 이름 ... T> 표준 : : ostream에 & 연산자 << (표준 : : ostream에 및 운영 체제, const를 표준 당신이 알고 있다고 가정 : : : 전자는 다른 것 같아요 tuple & t)'나쁜 계획입니까? – Yakk

+0

@Yakk 저는 이것을 일부 코드를 디버깅 할 때만 도우미로 사용하고 있습니다. 그래서 저는 솔루션을 매우 일반적인 것으로 만들기위한 모든 세부 사항을 다루지 않았습니다. 예를 들어 직설 사례에 대해서는 생각하지 않았습니다. 그러나, 나는 그것에 대해 당신의 특별한 관심사가 무엇인지 궁금합니다. 나는 이걸로 무언가를 배우 겠다는 느낌을 가지고있다. :) – dvicino

+0

[이것이 작동하지 않는 이유에 대해 알아 내기] (http://coliru.stacked-crooked.com/a/7ea7fd8f91a9958e) – Yakk

답변

1
std::cout << std::make_tuple(2, 3.14159F, 2345.678) 

이 그 내부에서 std::ostream& operator<< <int, float, double>(std::ostream& os, const std::tuple<int, float, double>& t)

를 호출하면 tuple_printer<sizeof...(T), std::tuple<T...>>::print(os, t); 전화

입니다
void tuple_printer<3, std::tuple<int, float, double>>::print(
    std::ostream& os, 
    const std::tuple<std::tuple<int, float, double>>& t); 

두 배로 된 tuple에 유의하십시오. 명시 적으로 tuple을 하나의 인수로 T...에 전달하면 함수가이를 다른 튜플로 래핑합니다.

print 함수 내부, 당신은 t 단 하나 개의 요소를 가지고 있기 때문에 컴파일에 실패

std::get<2>(t) 

를 호출합니다. 다른 상황에서

, get<s-1>(t) 성공하지만 다음 operator<<에 그 전달하려고, 그래서 튜플이 아닌 근본적인 요소를 반환하지만 튜플 operator<< 아직 선언되지 않았습니다.

2

  1. tuple_printersize_t, tuple<T...>하지만 size_t, T...을하지 않습니다 또한 당신이 원하는 것

tuple_printer<sizeof...(T), T...> 

  2.와

tuple_printer<s-1, T...> 

tuple_printer<sizeof...(T), std::tuple<T...>> :

가와 tuple_printer<s-1, std::tuple<T...>> 교체 기본 템플릿의 문 순서가 littl이됩니다.

tuple_printer<s-1, T...>::print(os, t); 
os << ", "; 
os << std::get<s-1>(t);