2017-12-21 37 views
6

매개 변수 팩 및 일부 표준 일치 규칙을 사용하여 다른 함수를 사용하는 함수를 작성하려고합니다. 예를 들어 :여러 팩을 사용하는 매개 변수 팩 일치 규칙

TListElemsTVectorElems, 나는 어떤 std::tuple<T...>* 그래서 발신자가 명시 될 수 있습니다 추가 명확하게하기 위해
template <typename... TListElems, typename... TVectorElems> 
void goal(void (*fn)(std::list<TListElems>..., std::vector<TVectorElems>...)); 

: 잠시 g ++,

template <typename... TListElems, typename... TVectorElems> 
void foo(std::tuple<TListElems...>*, 
     std::tuple<TVectorElems...>*, 
     void (*)(std::list<TListElems>..., std::vector<TVectorElems>...)) 
{ 
    // blah blah blah 
} 

void bar(std::list<int>, std::list<unsigned>, std::vector<float>, std::vector<double>) 
{ 
    // blah blah blah 
} 

int main() 
{ 
    foo((std::tuple<int, unsigned>*) nullptr, 
     (std::tuple<float, double>*) nullptr, 
     &bar); 
} 

연타 행복하게 내가 기대하는 방식이 컴파일 (7.2.1)는 컴파일 오류 제공 : main에서

matching.cpp: In function ‘int main()’: 
matching.cpp:20:13: error: no matching function for call to ‘foo(std::tuple<int, unsigned int>*, std::tuple<float, double>*, void (*)(std::list<int>, std::list<unsigned int>, std::vector<float>, std::vector<double>))’ 
     &bar); 
      ^
matching.cpp:6:6: note: candidate: template<class ... TListElems, class ... TVectorElems> void foo(std::tuple<_Tps ...>*, std::tuple<_Elements ...>*, void (*)(std::list<TListElems>..., std::vector<TVectorElems>...)) 
void foo(std::tuple<TListElems...>*, 
     ^~~ 
matching.cpp:6:6: note: template argument deduction/substitution failed: 
matching.cpp:20:13: note: mismatched types ‘std::vector<TVectorElems>’ and ‘std::list<int>’ 
     &bar); 
      ^

을, 나는 기대foo에 대한 호출 유형 void (*)(std::list<int>, std::list<unsigned>, std::vector<float>, std::vector<double>) (일이 하나의 팩이있는 경우 운영 또는 내가 수동으로 오버로드를 쓴 경우 방법)의 수 fn을 선도 <float, double><int, unsigned>TVectorElemsTListElems을 추론합니다.

§14.8.2.5/10 표준 명시 적 작업에서 foo 예를 방지하기 위해 오는 가장 가까운 :

[Note: A function parameter pack can only occur at the end of a parameter-declaration-list (8.3.5). -end note]

fnstd::list<TListElems>... 비트는이 메모를 위반하는 그것 같이 보인다, 그러나 그것은 완전히 분명하지 않다 .

질문은 : 누구가 맞습니까? GCC, Clang 또는 다른 것?

답변

3

나는 그 소리가 바로 여기라고 생각합니다. void (*)(std::list<TListElems>..., std::vector<TVectorElems>...)에서

, TListElems...TVectorElems... 또한 a non-deduced context하게하는 a non-deduced context이다. 그러나 두 개의 파라미터 팩 은 두 개의 튜플 포인터 인수에서으로 공제가 가능하며 여기에는 use that deduction result도 가능할 것으로 예상됩니다.

나는 gcc bug 83542을 제출했다.

+0

§17.9.2.5/6은 Jarod42의 솔루션이 작동하는 이유를 제공합니다 (구체적으로 " 'A :: B, A )'으로 지정되면'A :: B'의'T'는 추론되지 않지만'A '의'T'는 추론 "), Clang이나 GCC가 실제로 정확한 해석을 가지고 있는지에 관해서는 모호합니다. –

2

당신은 비 추론 될 유형 모두 컴파일러 행복 할 수

template <typename T> 
struct non_deducible { 
    using type = T; 
}; 

template <typename T> using non_deducible_t = typename non_deducible<T>::type; 


template <typename... TListElems, typename... TVectorElems> 
void foo(std::tuple<TListElems...>*, 
     std::tuple<TVectorElems...>*, 
     void (*)(non_deducible_t<std::list<TListElems>>..., 
        non_deducible_t<std::vector<TVectorElems>>...)) 
{ 
    // blah blah blah 
} 

Demo

+0

나는'non_deducible_t'를 함수 포인터 타입 자체에 사용하고 싶습니다. 그래서'non_deducible_t ..., std :: vector ...)> *' – Yakk