2012-05-25 6 views
6

유형이 아닌 템플릿 매개 변수와 함께 유형이 아닌 템플릿 매개 변수가있는 템플릿에 유형을 분해 할 수있는 템플릿을 작성하고 싶습니다. 예를 들어 Array<5>template<int> Array5으로 분해하지만 모든 유형의 비 형식 템플릿 매개 변수 (정수형, 포인터, 멤버 포인터 등)에 대해 일반적으로 작동합니다. 템플릿 특수화와비 유형 템플릿 매개 변수 유형의 추상화

첫 번째 시도 :

template<typename T> struct foo { enum { n = 1 }; }; 

template<int x> struct bar { enum { n = x }; }; 

template<typename T, template<T> class X, T x> 
struct foo< X<x> > { enum { n = x }; }; // here x must be of integral type, but that's just for testing 

int main(int, char**) { return foo< bar<16> >::n; } 

연타 3.1은 말한다 :

test145.cpp:6:8: warning: class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used 
struct foo< X<x> > { enum { n = x }; }; 
     ^~~~~~~~~~~ 
test145.cpp:5:19: note: non-deducible template parameter 'T'      
template<typename T, template<T> class X, T x> 
       ^
1 warning generated. 

두 번째 시도, 함수 템플릿 :

template<typename T, T x> 
struct box 
{ 
    static constexpr T value() { return x; } 
}; 

template<typename T, template<T> class X, T x> 
box<T, x> foo(X<x>); 

template<int> struct asdf { }; 

int main(int, char**) { return decltype(foo(*(asdf<9>*)0))::value(); } 

연타는 말한다 :

test150.cpp:12:41: error: no matching function for call to 'foo' 
int main(int, char**) { return decltype(foo(*(asdf<9>*)0))::value(); } 
             ^~~ 
test150.cpp:8:11: note: candidate template ignored: couldn't infer template argument 'T' 
box<T, x> foo(X<x>); 
     ^
1 error generated. 

GCC 4.7은 비슷한 것을 말합니다.

이것은 기본적인 제한 사항입니까?

보너스 질문 : 그렇다면 단순한 일반 코드가 아니더라도 유한 양의 무한한 가능성을 모두 처리 할 수있는 방법이 있습니까? (예 : 포인터로는 어려워진다. 쓸데없는 것과 같은 이유 때문에 template<T>도 쓸 수 있다고 생각하지 않는다.)

내가 묻는 이유는 묻지 말아라.

+1

정확히 말해서 내가 필요한 것이 무엇인지 이해할 수 없다. –

+2

다음과 같이 요약 할 수 있다고 생각한다 : '템플릿 구조체 {{}'.'arg > :: template_'이'template Array'이고'arg > :: type'이'int' 인 템플릿'arg'를 쓰는 것이 가능한가? (그렇다면?)'arg' > :: value'은'5' (그리고'int' 형)입니다. 또한 가능한 모든 타입이 아닌 템플릿 인자가 이런 방식으로 처리 될 수 있도록 만듭니다. – reima

+0

그건 기본적으로. 내가 할 수있는 것보다 더 명확하게 넣어 주셔서 감사합니다! – glaebhoerl

답변

2

이 다른 질문은 기본적으로 같은 일을 요구하고 있지만, 템플릿 유형 오히려 템플릿 비 형 매개 변수보다 매개 변수에 대한 : template metaprogramming: (trait for?) dissecting a specified template into types T<T2,T3 N,T4, ...>

를 들어 유형 매개 변수, 정말 쉽습니다. 코드는 다음과 같습니다 아직 가능하다면

#include <tuple> 
#include <vector> 

template <class T> struct explode; 

template <template <class... Args> class T, class... N> 
struct explode<T<N...>> 
{ 
    typedef T<N...> type; 
    template <class... Args> using template_ = T<Args...>; 
    template <int I> using type_parameter = 
     typename std::tuple_element<I, std::tuple<N...>>::type; 
}; 

#if TESTING 
void test_harness() 
{ 
    typedef explode<std::vector<int>> exv; 

    exv::template_<char> vchar; // The second parameter still has its default argument! 
    exv::template_<exv::type_parameter<0>, exv::type_parameter<1>> vint; 

    static_assert(std::is_same<exv::template_<char>, std::vector<char>>::value, ""); 
    static_assert(std::is_same<decltype(vchar), std::vector<char>>::value, ""); 
    static_assert(std::is_same<decltype(vint), std::vector<int>>::value, ""); 
    static_assert(std::is_same<exv::type, std::vector<int>>::value, ""); 
    static_assert(std::is_same<exv::type_parameter<0>, int>::value, ""); 
    static_assert(std::is_same<exv::type_parameter<1>, std::allocator<int>>::value, ""); 
} 
#endif 

그러나 비 형 매개 변수에 대해, 내가 알아 낸하지 않았습니다. 비슷한 모양의 코드로 시작할 수 있습니다.

template <class... ArgTypes, template <ArgTypes... Args> class T, ArgTypes... N> 
struct explode<T<N...>> 
{ 
    typedef T<N...> type; 
    template <ArgTypes... Args> using template_ = T<Args...>; 
    template <int I> using type_of_parameter = 
     typename std::tuple_element<I, std::tuple<ArgTypes...>>::type; 
    template <int I> struct nontype_parameter { 
     static constexpr type_of_parameter<I> value() { 
      return std::get<I>(std::tuple<ArgTypes...>(N...)); 
     } 
    }; 
}; 

}};

하지만 연타가 (적어도)을 허용하지 않습니다

test.cc:8:8: warning: class template partial specialization contains a template 
     parameter that can not be deduced; this partial specialization will never 
     be used 
struct explode<T<N...>> 
     ^~~~~~~~~~~~~~~~ 
test.cc:7:20: note: non-deducible template parameter 'ArgTypes' 
template <class... ArgTypes, template <ArgTypes... Args> class T, ArgTypes... N> 
       ^

을 당신이 그 문제가 해결 어떻게 든 갈 만든 경우에도, 당신은 여전히 ​​손으로 코딩 constexpr 버전으로 std::get를 교체해야 할 것, 표준 라이브러리의 std::get은 어떤 이유로 든 constexpr이 아니기 때문입니다.

+0

그래, 근본적으로 첫 번째 예를 들었을 때와 동일한 문제입니다. 템플릿 매개 변수가 템플릿 매개 변수 목록에만 있지만 특수화 인수에는없는 경우 유추 할 수 없습니다. 아마도 표준은 이것을 명령합니다. 그렇지 않으면 불가능할 것으로 보이는 것처럼 보이지 않기 때문입니다. – glaebhoerl