आम तौर पर सफल होने के लिए कटौती के लिए, तर्क को पैरामीटर के समान सामान्य रूप की आवश्यकता होती है। कुछ अपवाद हैं जहां T &&
U &
(T = U &
चुनकर) से लिया जा सकता है, लेकिन इस मामले के लिए ऐसा कोई अपवाद निर्दिष्ट नहीं किया गया था।
14.8.2.5 एक प्रकार से टेम्पलेट तर्क बात का अनुमान लगाना [temp.deduct.type]
8 एक टेम्पलेट प्रकार तर्क T
, एक टेम्पलेट टेम्पलेट तर्क TT
या एक टेम्पलेट गैर प्रकार तर्क i
हो सकता है निष्कर्ष निकाला है, तो P
और A
निम्नलिखित रूपों में से एक है:
[...]
T&
T&&
[...]
यह बिल्कुल स्पष्ट नहीं है, लेकिन इस P
(पैरामीटर) और A
(तर्क) की आवश्यकता है दोनों को एक ही रूप है। उन्हें T&
फॉर्म, या दोनों T&&
फ़ॉर्म दोनों की आवश्यकता है।अपवाद, जिन परिस्थितियों में T &&
U &
से निष्कर्ष निकाला जा सकता है, मिलान से पहले सादा T
करने के लिए T &&
बदलते द्वारा किया जाता है जगह लेता है, सीमित परिस्थितियों में:
10 इसी प्रकार, यदि P
एक रूप है कि (T)
शामिल है, तो संबंधित पैरामीटर प्रकार सूची P
की से प्रत्येक पैरामीटर प्रकार Pi
इसी पैरामीटर प्रकार इसी पैरामीटर प्रकार सूची A
की की Ai
साथ तुलना में है। यदि P
और A
कार्य प्रकार हैं जो किसी फ़ंक्शन टेम्पलेट (14.8.2.2) का पता लेते समय कटौती से उत्पन्न होते हैं या फ़ंक्शन घोषणा (14.8.2.6) और Pi
और Ai
से टेम्पलेट तर्कों को कम करते समय शीर्ष-स्तर के पैरामीटर होते हैं पैरामीटर प्रकार सूची P
और A
की क्रमश: Pi
अगर यह एक सीवी-अयोग्य टेम्पलेट पैरामीटर के लिए एक rvalue संदर्भ और Ai
एक lvalue संदर्भ, जिस स्थिति में Pi
के प्रकार के टेम्पलेट में परिवर्तित हो जाता है निकाला जाता है पैरामीटर प्रकार (यानी, T&&
को T
में बदला गया है)। [...]
और
14.8.2.1 एक समारोह कॉल [temp.deduct.call]
3 [...] तो P
है से टेम्पलेट तर्क बात का अनुमान लगाना एक सीवी-अयोग्य टेम्पलेट पैरामीटर का एक रेवल्यू संदर्भ और तर्क एक लवल्यू है, प्रकार A
"के प्रकार का उपयोग" A
"के प्रकार का उपयोग प्रकार के कटौती के लिए A
के स्थान पर किया जाता है। [...]
लेकिन आपके परिदृश्य पर कोई भी अपवाद लागू नहीं होता है।
यह इस एक ही सिद्धांत है कि renders है
template <typename T> struct S { };
template <typename T> void f(S<const T>) { }
int main() { f(S<void()>()); }
अमान्य: const T
, void()
से निष्कर्ष निकाला नहीं जा सकता है, भले ही T = void()
वास्तव में परिणाम देना होगा, और बुला f<void()>
कामयाब होने की।
Wintermute के नष्ट कर दिया जवाब से पता चला कि आप
template <typename... Types> // vv-- change here
void print_tuple(const std::tuple<Types...>& value)
बजाय का उपयोग कर सकते हैं: इस Types
lvalue संदर्भ के रूप में निष्कर्ष निकाला जा करने के लिए अनुमति देता है, rvalue संदर्भ के रूप में, या गैर संदर्भ, के प्रकार के आधार के रूप में value
।
आपको विशेष रूप से टुपल को कैप्चर करने की भी आवश्यकता नहीं है। क्यों न केवल 'टेम्पलेट शून्य प्रिंट_टुपल (टुपल और मूल्य) '? –
0x499602D2
चूंकि यह कम से कम दो लोगों के लिए स्पष्ट नहीं था: आपकी 'print_tuple' परिभाषा * करता है * कॉल को अनुमति देता है अगर टेम्पलेट तर्क स्पष्ट रूप से 'print_tuple' के रूप में निर्दिष्ट किए जाते हैं। यह एक अच्छा सवाल है कि संकलक पहले 'प्रकार' को अलग-अलग क्यों कम कर रहा है। –
hvd
@hvd ऐसा इसलिए हो सकता है क्योंकि एक स्ट्रिंग अक्षर एक लवल है और इसे अग्रेषित किया जा रहा है। – 0x499602D2