2015-02-03 1 views
2

나중에 파생 클래스를 "확장"한다고 가정하고이 클래스를 Base 및 확장자 Derived이라고합시다. 클래스의 템플릿 서명이 고정되어 있으므로 (템플릿 인수를 클래스로 변경할 수 없음)을 변경할 수 없습니다. Derived 클래스의 작성자는 Base에 대해서는 아무것도 알지 못하며, 일 수도 있고은 생성자에 대한 인수를 취할 수 있습니다.단일 인수를 유지하면서 가변 인수 목록을 전달하는 방법

그러나 최종 파생 클래스의 호출자는 전달되어야하는 인수의 수를 알고 있습니다. 이 Derived 확장 프로그램을 작성하려면 어떻게해야합니까?

struct Base 
{ 
    Base(int baseArg) {} 
}; 

struct Derived : public Base 
{ 
    template <typename... Args> 
    Derived(Args&&... args, int derivedArg) 
    : 
     Base(std::forward<Args>(args)...) 
    { 
    } 
}; 

내가 Derived d(1, 1);run this하려고 나는 다음 erorr 메시지를 얻을 :

prog.cpp: In function 'int main()': 
prog.cpp:19:16: error: no matching function for call to 'Derived::Derived(int, int)' 
    Derived d(1, 1); 
       ^
prog.cpp:19:16: note: candidates are: 
prog.cpp:11:2: note: template<class ... Args> Derived::Derived(Args&& ..., int) 
    Derived(Args&&... args, int myArg) 
^
prog.cpp:11:2: note: template argument deduction/substitution failed: 
prog.cpp:19:16: note: candidate expects 1 argument, 2 provided 
    Derived d(1, 1); 
       ^
prog.cpp:8:8: note: constexpr Derived::Derived(const Derived&) 
struct Derived : public Base 
     ^
prog.cpp:8:8: note: candidate expects 1 argument, 2 provided 
prog.cpp:8:8: note: constexpr Derived::Derived(Derived&&) 
prog.cpp:8:8: note: candidate expects 1 argument, 2 provided 

Derived에 생성자 자체를 구성하는 첫 번째를 사용하여,이 개 인수를해야하고 여기에 내가 무엇을 가지고 2를 기본 클래스에 전달합니다. 왜이 기능이 작동하지 않습니까?

+0

함수 인자 – BlamKiwi

답변

4

Derived 생성자는 추론되지 않은 컨텍스트입니다. §14.8.2.5/5 temp.deduct.type]에서 :

비 콘텍스트 추론은 다음

- [...]

-없는 함수 파라미터 팩 매개 변수 선언 목록 끝에 끝납니다. 귀하의 경우에는

는 매개 변수 팩은 말에 있지 - 거기 후 하나 개 더 인수는, 그래서 그것은 잘못 형성 프로그램을 만드는 비 추론 문맥입니다. 모든하지만 마지막에서, 인수

template<size_t n, class...Args> 
auto nth(Args&&... args) 
->typename std::tuple_element<n,std::tuple<Args&&...>>::type 
{ 
    return std::get<n>(std::forward_as_tuple(std::forward<Args>(args)...)); 
} 

이 마지막을 추출하는 위를 사용하고 :

template <typename... Args> 
Derived(int derivedArg, Args&&... args) // totally OK 
: 
    Base(std::forward<Args>(args)...) 
{ 
} 
+0

위의 첫 번째 인수를 넣으십시오. 표준 참조를 정말 고맙게 생각합니다 : – arman

5

nth 일부 매개 변수의 n 번째 요소를 가져옵니다 간단한 솔루션은 순서를 반전하는 것입니다 적절한 장소로 보내

struct Derived : public Base { 
    struct tag{}; 
    template <typename... Args> 
    Derived(Args&&... args) : Derived(
    tag{}, 
    std::make_index_sequence<sizeof...(Args)-1>{}, 
    std::forward<Args>(args)... 
){} 
    template<size_t...Is, class...Args> 
    Derived(tag, std::index_sequence<Is...>, Args&&...args): 
    Base(nth<Is>(std::forward<Args>(args)...)...) 
    { 
    int derivedArg = nth<sizeof...(Args)-1>(std::forward<Args>(args)...); 
    } 
}; 

우리는 처음 n-1 요소에 대한 순서를 구축 기본에 전달하고, 자신을 위해 마지막 요소를 저장합니다.

그러나 추가 인수를 먼저 쓰면 훨씬 쉽습니다.

+0

'nth'의 C++ 버전 14는'decltype (auto)'을 사용해야합니다. –

+0

@ t.c. yep : 그러나 tuple 요소를 사용하여 C++ 11 기간을 만들었습니다. – Yakk

+0

'태그'란 무엇입니까? (첫 번째'std :: forward' 다음에'...'가 필요하다.) – 0x499602D2

관련 문제