2017-06-02 34 views
8

निम्नलिखित कोड पर विचार करें:कटौती गाइड और variadic टेम्पलेट्स

#include <tuple> 
#include <iostream> 

template <class T> 
struct custom_wrapper 
{ 
    template <class Arg> 
    custom_wrapper(Arg arg): data(arg) {} 
    T data; 
}; 

template <class Arg> 
custom_wrapper(Arg arg) -> custom_wrapper<Arg>; 

template <class... T> 
struct custom_tuple 
{ 
    template <class... Args> 
    custom_tuple(Args... args): data(args...) {} 
    std::tuple<T...> data; 
}; 

template <class... Args> 
custom_tuple(Args... args) -> custom_tuple<Args...>; 

int main(int argc, char* argv[]) 
{ 
    custom_wrapper<int> w1(42); // OK 
    custom_wrapper w2(42);  // OK 
    custom_tuple<int> t1(42); // OK 
    custom_tuple t2(42);   // Fails 
    return 0; 
} 

लाइन है कि जी ++ 7 के तहत निम्न त्रुटि लौटने में विफल रहता है:

variadic_deduction_guide.cpp: In instantiation of 'custom_tuple<T>::custom_tuple(Args ...) [with Args = {int}; T = {}]': 
variadic_deduction_guide.cpp:31:23: required from here 
variadic_deduction_guide.cpp:19:45: error: no matching function for call to 'std::tuple<>::tuple(int&)' 
    custom_tuple(Args... args): data(args...) {} 

सामान्य है कि है या कि एक संकलक बग है ?

उत्तर

3

यह gcc bug 80871 है। निम्नानुसार है कि कोड अच्छी तरह से गठित क्यों हुआ है (और t2 का निर्णय लेने में यह सही है कि custom_tuple<int> है)।


पता लगाना कि क्या करना है के साथ

custom_tuple t2(42); 

मूल रूप से कार्यों का एक समूह synthesizing और उन पर अधिभार संकल्प प्रदर्शन शामिल है के लिए प्रक्रिया।

template <class... T, class... Args> 
custom_tuple<T...> foo(Args...);  // the constructor 

template <class... Args> 
custom_tuple<Args...> foo(Args...); // the deduction guide 

इस बिंदु यह एक क्या एक "अनुगामी पैरामीटर पैक" [temp.arg.explicit]/3 के अनुसार है की अपनी व्याख्या के आधार पर अपने स्वयं का रोमांच चुनें है से:: प्रासंगिक उम्मीदवारों एक निर्माता से संश्लेषित कार्य करता है और कटौती गाइड कर रहे हैं

एक पिछला टेम्पलेट पैरामीटर पैक जिसे अन्यथा नहीं लिया गया है, टेम्पलेट तर्कों के खाली अनुक्रम को घटाया जाएगा। यदि सभी टेम्पलेट तर्कों को घटाया जा सकता है, तो वे सभी को छोड़ दिया जा सकता है; इस मामले में, खाली टेम्पलेट तर्क सूची <> स्वयं भी छोड़ी जा सकती है।

T... अनुगामी नहीं है

इस मामले में आसान है। हमारे पास केवल एक व्यवहार्य उम्मीदवार है (क्योंकि T... deducible नहीं है) - कटौती-गाइड उम्मीदवार। हम Args... को {int} के रूप में घटाते हैं, इसलिए हम custom_tuple<int> के साथ समाप्त होते हैं।

T...

दोनों जीसीसी और बजना पीछे चल रही है वास्तव में निर्माता के लिए सफल होने के लिए विचार करते हैं कटौती। इसलिए हम [over.match.best] में tiebreakers पर जाएँ:

इन परिभाषाओं को देखते हुए, एक व्यवहार्य समारोह F1 एक व्यवहार्य समारोह F2 अगर तुलना में एक बेहतर समारोह होने के लिए परिभाषित किया गया है [...]

  • F1 और F2 फ़ंक्शन टेम्पलेट विशेषज्ञता हैं, और F1 के लिए फ़ंक्शन टेम्पलेट 0 tem36.func.order] में वर्णित आंशिक क्रम नियमों के अनुसार F2 के लिए टेम्पलेट से अधिक विशिष्ट है, या यदि नहीं,
  • F1 एक कटौती-गाइड ([over.match.class.deduct]) से उत्पन्न होता है और F2 नहीं है, या यदि नहीं, तो [...]

आंशिक आदेश के प्रयोजनों के लिए, relevant types सिर्फ उन जो मानकों के संगत होती हैं, और हम ignore unused template parameters करने की अनुमति है, इसलिए कोई भी समारोह टेम्पलेट अन्य की तुलना में अधिक विशिष्ट माना जाता है।

यह हमें कटौती-गाइड को बस पसंद करने के लिए छोड़ देता है, जो इस पूरी प्रक्रिया का सबसे आसान कदम रहा है। हम Args... को {int} के रूप में घटाते हैं, इसलिए हम custom_tuple<int> के साथ समाप्त होते हैं।


किसी भी तरह से, custom_tuple<int> सही निर्णय है।

+0

ओएम के कोड पर हम्म, जीसीसी और क्लैंग ट्रंक असहमत हैं, और मैं वास्तव में यहां आश्वस्त नहीं हूं। सबसे पहले, 'टी'" पीछे "है? (यह एक बदतर परिभाषित शब्द है।) दूसरा, क्या आप प्रदर्शन कर सकते हैं कि कन्स्ट्रक्शन कटौती मार्गदर्शिका से अधिक विशिष्ट कैसे है? –

+0

@ टी.सी. लेकिन कटौती-गाइड के साथ काम कर क्लैंग को देखने के लिए अच्छा लगा! यह बहुत हाल ही में होना चाहिए। – Barry

+0

यहां संदर्भ एक फंक्शन कॉल है, इसलिए ["आंशिक क्रम \ \ के लिए उपयोग किए जाने वाले प्रकार उन फ़ंक्शन पैरामीटर प्रकार हैं जिनके लिए फ़ंक्शन कॉल में तर्क हैं"] (https://timsong-cpp.github.io/cppwp /temp.deduct.partial#3.1)। और आंशिक क्रमिक उद्देश्यों के लिए, ["एक टेम्पलेट पैरामीटर एक मूल्य के बिना रह सकता है बशर्ते इसे आंशिक क्रम के लिए उपयोग किए जाने वाले प्रकारों में उपयोग नहीं किया जाता है"] (https://timsong-cpp.github.io/cppwp/temp.deduct। आंशिक # 12), और 'टी ...' नहीं है। तो वास्तव में एक दूसरे से कैसे अधिक विशिष्ट है? कटौती में कौन सी दिशा विफल होती है, और कैसे? –

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