2014-05-10 3 views
3

매개 변수 집합이 다른 임의의 튜플 목록을 허용하는 가변 템플릿을 사용하여 함수를 작성할 수 있습니까? 그래서 당신은 다음과 같은 것을 갖게 될 것입니다 :중첩 된 가변 템플릿이있는 함수

template< /* some crazy variadic thing...*/ > 
void func(...) {} 

func(make_tuple(1,2), make_tuple("hello")); 

SFINAE to the rescue! Jeffery의 대답을 조금 더 듣고 나는이 작은 발췌문을 썼다. func의 인수 목록에 튜플이 아닌 다른 유형을 넣을 수 있습니다. 컴파일 및 실행하면 템플릿 클래스가 아닌 첫 번째 유형에 도달 할 때 인쇄 체인이 끊어집니다. seqgenshere에서 제공됩니다.

template<typename T> 
int print(T& t) { 
     cout << t << " "; 
     return 0; 
} 

template<typename... T> void dumby(T...) {} 

// so other template classes don't cause error (see bar below) 
template<typename... A> 
void expand(A... a) {} 

template<typename... A, int... S> 
void expand(tuple<A...> a, seq<S...>) { 
     dumby(print(get<S>(a))...); 
     cout << endl; 
} 

template<class... Types> 
void func(Types...) {} 

template<template<typename...> class A, class... Types, class... tup_types> 
void func(A<tup_types...> a, Types... args) { 
     expand(a, typename gens<sizeof...(tup_types)>::type()); 

     func(args...); 
} 

template<typename... A> struct bar {}; 

int main() { 
     func(make_tuple(0,1), make_tuple(2), 1, make_tuple("hello"), 0); 
     func(make_tuple(0,1), bar<int,int>(), make_tuple(2), 1, make_tuple("hello"), 0); 
} 

실용적인 사례를 찾아 사용 해봐야 만합니다.하지만 잠깐 성공하겠습니다.

+0

무엇 유스 케이스가 될까요? 시체를 어떻게 써줄까요? – Shoe

+0

음, C++입니다. 명백한 대답은 뻔뻔스런 예입니다 : P하지만 누군가가 정교하게 신경을 쓸 것이라고 확신합니다. – CoffeeandCode

+0

@CoffeeandCode, 사실 불가능합니다. – Shoe

답변

3

불가능합니다. 인수 유형을 static_assert 또는 std::enable_if과 동일하게 적용 할 수는 있지만, 불행한 현실은 std::tuple이므로 클래스 템플릿이므로 여러 유형을 생성 할 수 있습니다.

가장 좋은 방법은 SFINAE을 사용하는 것입니다. 예를 들어 :

template<class A> 
void func(A a) { 
    std::cout << "First of last: " << std::get<0>(a) << '\n'; 
} 

template<class A, class... Types> 
void func(A a, Types... args) { 
    std::cout << "First of element: " << std::get<0>(a) << '\n'; 
    func(args...); 
} 

Live demo

위의 예 will succeed 모든 요소가 튜플은, but fail 그들은하지 않을 때.

+0

'template void func (Types ...)'가 필요한 이유는 무엇입니까? – ikh

3

예, 터플을 취하는 기본 함수를 사용하고 가변 템플릿/매개 변수와 같은 이름의 함수를 만듭니다.

template<typename ... Types> 
void func(const std::tuple<Types...> &Tuple){ 
    // work with tuple 
} 

template<typename TupleType, typename ... TupleTypes> 
void func(const TupleType &arg, const TupleTypes &... args){ 
    func(arg); 
    func(args...); 
} 

int main(){ 
    func(std::make_tuple(1, 2), std::make_tuple("hello")); 
} 

이것은 당신이 tuplethrow 또는 static_assert 또는 당신이 무엇을 당신이 좋아하지 않는 것을 건너 또는 당신도 갈 수있을 때 당신이 좋아하는의 종류의 수를 알 수있는 당신에게 있다는 점에서 많은 유연성을 줄 것이다 더 나아가 함수에서 std::enable_if을 사용하면 튜플을 사용하여 특정 조건 만 허용 할 수 있습니다!

당신이 요청으로이 기능은 std::tuple 작동하지만 당신이 첫 번째 함수를 변경하여이 유형의 여러 템플릿 인수를 어떤 용기의 사용을 허용 그것을 더 확장 할 수 :

template<typename ... Types, template<typename...> class TupleType> 
void func(const TupleType<Types...> &Tuple){ 
    // Work with any type inter-face-able like a tuple 
}