2017-12-21 105 views
6

मैं एक फ़ंक्शन लिखने की कोशिश कर रहा हूं जो पैरामीटर पैक और कुछ मानक मिलान नियमों का उपयोग करके एक और फ़ंक्शन लेता है। एक उदाहरण के रूप:एकाधिक पैक के साथ पैरामीटर पैक मिलान नियम

template <typename... TListElems, typename... TVectorElems> 
void goal(void (*fn)(std::list<TListElems>..., std::vector<TVectorElems>...)); 

आदेश TListElems और TVectorElems, मैं कुछ std::tuple<T...>* तो एक फोन करने वाले स्पष्ट हो सकता है जोड़ा को स्पष्ट करने के लिए:

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) संकलन त्रुटि देता है:

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); 
      ^

main में, मैं उम्मीद करेंगेfoo करने के लिए कॉल <int, unsigned> और TVectorElems<float, double> के रूप में के रूप में TListElems निकालना, प्रमुख fn प्रकार void (*)(std::list<int>, std::list<unsigned>, std::vector<float>, std::vector<double>) (जिस तरह से चीजें काम करते हैं जब वहाँ केवल एक ही पैक है या अगर मैं मैन्युअल रूप से अधिभार लिखा था) की हो।

§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]

fn की std::list<TListElems>... बिट यह की तरह लगता है इस नोट का उल्लंघन होगा, लेकिन यह पूरी तरह से स्पष्ट नहीं है ।

सवाल यह है: कौन सही है? जीसीसी, क्लैंग, या कुछ और?

उत्तर

3

मुझे लगता है कि बजना यहीं है।

void (*)(std::list<TListElems>..., std::vector<TVectorElems>...) में, TListElems...a non-deduced context है, जो बनाता है TVectorElems... भी a non-deduced context। लेकिन दोनों पैरामीटर पैक दो ट्यूपल पॉइंटर तर्कों से deducible हैं, और यह भी use that deduction result यहां भी सक्षम होने की उम्मीद है।

मैंने gcc bug 83542 दायर किया।

+0

§17.9.2.5/6 कारण बताता है कि जारोड 42 का समाधान क्यों काम करता है (विशेष रूप से: "यदि एक प्रकार 'शून्य एफ (टाइपनाम ए :: बी, ए )', 'टी 0 'में बी' '' '' '' '' '' '' 0'' कटौती "), लेकिन यह मेरे लिए संदिग्ध है कि अगर क्लैंग या जीसीसी में वास्तव में सही व्याख्या है। –

2

आप खुश गैर निगम्य प्रकार के साथ दोनों compilers कर सकते हैं:

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

संबंधित मुद्दे