2014-02-26 3 views
2

나는 다음과 같이 두 가지 믹스 인 클래스에 일련의 매개 변수를 전달하기 위해 노력하고있어에 튜플을 전달 :가변 인자 믹스 인 클래스

template <typename... Checkers> 
class Checker : public Checkers... { 
public: 
    template<typename... Args> 
    Checker(Args&&... args) : Checkers(std::forward<Args>(args))... { } 
}; 

template <typename... Handlers> 
class Handler : public Handlers... { 
public: 
    template <typename... Args> 
    Handler(Args&&... args) : Handlers(std::forward<Args>(args))... { } 
}; 

template <typename C, typename H> 
class Tester : public C, H { 
public: 
    template <typename... ArgC, typename... ArgH> 
    Tester(std::tuple<ArgC...>&& argc, ArgH&&... argh) : C(argc), H(argh...) { 
    } 
}; 

검사 및 핸들러에 대해 서로 다른 요구 사항과 믹스 인 클래스의 두 개의 서로 다른 모음입니다 각 구성원은 공통 요구 사항을 공유하지만 모두 필요합니다. 필자는 Tester에서 double variadic 구조를 수행 할 수 없다는 것을 알았습니다. (컴파일러는 인수를 나눌 위치를 추론 할 수 없으므로 Checker에 Handler와 None 모두 전달합니다.) 그래서 Tuple과 Handler 인수에 Checker 인수를 전달합니다. 가변성 목록. 문제는 Checker의 생성자가 이러한 매개 변수를 기반으로 전달하는 것입니다. Handler의 생성자는 가변적 인 목록이기 때문에 Handler가 처리 할 수 ​​있지만 Checker는 튜플을 가져 오지만 Forward와 같이 튜플의 요소를 전달할 수는 없습니다. 가변 인자 목록을 사용할 수 있습니다.

모든 조언을 주시면 감사하겠습니다. 감사.

추가

각각 어떻게 든 앞으로 그 튜플의 각 요소 중 하나) Checkerargc를 풀고의 가변 생성자 또는 b) Checker 확인의 생성자 튜플을 가지고있는 솔루션이 될 것이다 Checker의 믹스 인 염기, Checkers.... std::pair에는 고정 인수 목록으로 터플을 전달하는 트릭이 있습니다. 예를 들어, 3 진법 생성자로 std::piecewise_construct 유형 마커를 사용하여 언팩합니다. 그러나 이것이 어떻게 될지는 알 수 없습니다. 여기에 적용됩니다. 나는 의 GCC 4.8.1 구현을보고 std::piecewise_construct으로 알아낼 수 없었다. 나는 템플릿을 메타 프로그래밍 (예 : 현대 C + + 디자인C++ 템플릿 Metaprogramming 예전)에 대한 이전, C + +에서 11 권의 책을 읽었지만 지금은 표준이 있고 나는 지금 잃어 버렸어. Boost와 Loki를 피하려고 노력했다.

추가

는 GCC 4.7.2 적어도 을 준수해야합니다. 내가 찾은 솔루션은 std::pair을 기반으로 발견되었습니다 , 내 빌드 시스템에서 지원되지 않는 GCC 4.8.1까지 사용할 수 없었던 생성자 상속이 필요합니다.

추가

4.6.3 GCC 있지만 지원이 좋은 것, 위임 생성자 그래서 해당 언어의 기능에 액세스 할 수 있어야합니다 4.7.2에 추가되었다. 위의 자신의 블로그에 지정된

+1

[이 질문은]있을 수 있습니다. (http://stackoverflow.com/questions/10766112/c11-i-can-go-from-multiple-args-to-tuple-but-can-i-go-from 와 - 배수) 도움이 될 수 있습니다. – maverik

+0

문제는 기본적으로 호출 컨벤션에 제한이있는 기본 생성자를 호출하므로 처음 읽는 것은 작동하지 않습니다.하지만 내가 처리 할 수 ​​있는지 알아보기 위해 그것을 뒤틀어 볼 수 있는지 확인해 보겠습니다. 찾고있어. – TimeHorse

+0

'std :: pair'의 "조각 별"생성자를 에뮬레이션 할 수 있습니다. –

답변

2

http://cpptruths.blogspot.fr/2012/06/perfect-forwarding-of-parameter-groups.html

Davidbrcz의 솔루션은 내 수수께끼를 해결하기에 충분했다. 솔루션은 다소 복잡하기 때문에 그의 페이지로 안내 하겠지만 기본 아이디어는 숫자 인덱스 튜플 인 à la std :: maketuple (0, 1, 2, ...)을 만드는 것입니다.) 튜플에는 열거 할 필요가있는 튜플의 다양한 멤버의 인덱스가 들어 있습니다. M과 IdxM에 인수 인덱스의 같은 크기 튜플을 위의 예에서 C 또는 H 중 하나로 M 들어

M(std::forward<ArgM>(std::get<IdxM>(argm))...) 

및 ArgM : 그럼 그냥 사용합니다.목록의 길이가 같기 때문에 목록이 일렬로 매개 변수로 롤아웃되고 튜플이 압축 해제됩니다.

인덱스 튜플을 구현 세부 사항으로 숨기는 복잡한 단계를 원하기 때문에 제한 사항은 생성자 위임을 사용하여 공용 생성자가 2 개의 튜플을 가져 와서 생성자 생성자로 위임하는 것입니다. 2 값 튜플 및 2 인덱스 튜플. GCC 4.7.2는 위임 된 생성자를 지원하지만 4.6.3은 그렇지 않습니다.

#if __GNUC__ < 4 || __GNUC_MINOR__ <= 6 
#define ZEROPARAM , detail::make_indices<>::type() 
#define ONEPARAM , detail::make_indices<int>::type() 
#define TWOPARAM , detail::make_indices<int, int>::type() 
#define THREEPARAM , detail::make_indices<int, int, int>::type() 
#define FOURPARAM , detail::make_indices<int, int, int, int>::type() 
#define FIVEPARAM , detail::make_indices<int, int, int, int, int>::type() 
#define SIXPARAM , detail::make_indices<int, int, int, int, int, int>::type() 
#define SEVENPARAM , detail::make_indices<int, int, int, int, int, int, int>::type() 
#define EIGHTPARAM , detail::make_indices<int, int, int, int, int, int, int, int>::type() 
#define NINEPARAM , detail::make_indices<int, int, int, int, int, int, int, int, int>::type() 
#define TENPARAM , detail::make_indices<int, int, int, int, int, int, int, int, int, int>::type() 
#else // __GNUC__ < 4 || __GNUC_MINOR__ <= 6 
#define ZEROPARAM 
#define ONEPARAM 
#define TWOPARAM 
#define THREEPARAM 
#define FOURPARAM 
#define FIVEPARAM 
#define SIXPARAM 
#define SEVENPARAM 
#define EIGHTPARAM 
#define NINEPARAM 
#define TENPARAM 
#endif // __GNUC__ < 4 || __GNUC_MINOR__ <= 6 
:

이 해결하기 위해, 당신은 4 매개 변수 생성자 (값의 2 튜플, 지수의 2 개 튜플) 공개 한 후 나는 인덱스 튜플 매개 변수를 입력하는 매크로를 작성을해야

그리고 주어진 테스터의 구성에 따라 적절한 매크로를 추가하십시오. 최소한 GCC 4.6.3에 여전히 사람들이있는 반면, 모든 사람들을 적어도 4.7.2 그리고 선호하는 4.8.1로 만들 수는 있습니다. :)

나는 Davidbrcz에게 해결책을 제시해 줄 수 있었으면 좋겠지 만, 적어도 이것은 비슷한 문제에 직면 한 사람들이 자신의 구체적인 경우에 적용 할 수있는 도움이 될 것입니다. 가장 중요한 것은 make_indices 템플릿 클래스를 복사하여 실제 작업을 수행하는 것입니다. 나머지는 케이크 도보 다!