2012-02-04 2 views
0

다른 튜플의 처음 n 개 요소에서 튜플을 생성하려고합니다. 이것은 내가 사용하는 재귀입니다 (여기서 유용한 것은 계산하지 않습니다).GCC에서이 템플릿 전문화가 작동하지 않는 이유는 무엇입니까?

이상하게도 g ++ 4.6.1을 사용하여 이해할 수 있지만 front<0,…>front<n,…>보다 특수하며 선택해야합니다. 이 버그입니까, 전문화에 대해 혼란 스럽습니까?

#include <tuple> 

template<std::size_t, typename> 
struct front; 

#if 0 
// This works, but I only want one case. 
template<typename Head, typename... Tail> 
struct front<0, std::tuple<Head, Tail...>> { 
    typedef std::tuple<> type; 
}; 
template<typename Head> 
struct front<0, std::tuple<Head>> { 
    typedef std::tuple<> type; 
}; 
template<> 
struct front<0, std::tuple<>> { 
    typedef std::tuple<> type; 
}; 
#elseif 0 
// this doesn't work, but I don't understand why: 
// ambiguous class template instantiation, candidates are: 
// struct front<0u, std::tuple<_Elements ...> > 
// struct front<n, std::tuple<_Head, _Tail ...> > 
template<typename... Tail> 
struct front<0, std::tuple<Tail...>> { 
    typedef std::tuple<> type; 
}; 
#else 
// neither does this: 
// ambiguous class template instantiation, candidates are: 
// struct front<0u, T> 
// struct front<n, std::tuple<_Head, _Tail ...> > 
template<typename T> 
struct front<0, T> { 
    typedef std::tuple<> type; 
}; 
#endif 
// this makes no sense, but it's short. 
template<std::size_t n, typename Head, typename... Tail> 
struct front<n, std::tuple<Head, Tail...>> { 
    typedef typename front<n - 1, std::tuple<Tail...>>::type type; 
}; 
// check all cases, error includes calculated type: 
front<0, std::tuple<int, float, double, long>>::type x0 = 0; 
front<2, std::tuple<int, float, double, long>>::type x2 = 0; 
front<4, std::tuple<int, float, double, long>>::type x4 = 0; 

답변

2

템플릿 인수는 왼쪽에서 오른쪽으로 선택되지 않습니다. 예, 0n보다 전문화되어 있지만 std::tuple<Head, Tail...>T보다 더 전문화되어 있습니다. 추가 전문화를 추가 할 수 있습니다.이 전문화는 두 인수 모두에서 가장 전문화되어 있습니다.

#include <tuple> 

template<typename A, typename B> 
struct front_helper; 

template<typename... A, typename... B> 
struct front_helper<std::tuple<A...>, std::tuple<B...>> { 
    typedef std::tuple<A..., B...> type; 
}; 

template<std::size_t, typename> 
struct front; 

template<> 
struct front<0, std::tuple<>> { 
    typedef std::tuple<> type; 
}; 
template<typename Head, typename... Tail> 
struct front<0, std::tuple<Head, Tail...>> { 
    typedef std::tuple<> type; 
}; 
template<std::size_t n, typename Head, typename... Tail> 
struct front<n, std::tuple<Head, Tail...>> { 
    typedef typename front_helper<std::tuple<Head>, typename front<n-1, std::tuple<Tail...>>::type>::type type; 
}; 

void x0(front<0, std::tuple<int, float, double, long>>::type) { } 
void x1(front<1, std::tuple<int, float, double, long>>::type) { } 
void x2(front<2, std::tuple<int, float, double, long>>::type) { } 
void x3(front<3, std::tuple<int, float, double, long>>::type) { } 
void x4(front<4, std::tuple<int, float, double, long>>::type) { } 

$ g++ test.cc -c -std=c++0x && nm -C test.o 
00000000 b .bss 
00000000 d .data 
00000000 t .text 
00000000 T x0(std::tuple<>) 
00000005 T x1(std::tuple<int>) 
0000000a T x2(std::tuple<int, float>) 
0000000f T x3(std::tuple<int, float, double>) 
00000014 T x4(std::tuple<int, float, double, long>) 
00000000 b std::(anonymous namespace)::ignore 
관련 문제