2017-08-03 21 views
13

मैं एक टेम्पलेट फ़ंक्शन को कोड करने का प्रयास कर रहा हूं जो एक एडीएल का उपयोग करता है जो get को संरचना/श्रेणी (tuple -esque) के सदस्यों को लाने के लिए हल करता है।क्यों एडीएल std :: के साथ सही फ़ंक्शन को हल नहीं करता है

#include <iostream> 
#include <utility> 
#include <tuple> 

int main() { 
    auto tup = std::make_tuple(1, 2); 
    std::cout << get<0>(tup) << std::endl; 
} 

मैं क्योंकि जो संरचित बाइंडिंग प्रस्ताव (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf §11.5.3) कैसे get struct से तत्वों को लाने के लिए प्रयोग किया जाता है के बारे में कहते हैं की यह कर रहा हूं। यह कहता है कि गैर-सदस्य get का उपयोग संरचनाओं के भीतर तत्वों को लाने के लिए किया जाता है।

मैं मान लिया है कि कोड से ऊपर, संकलन होगा क्योंकि ADL कारण होगा get समारोह std नाम स्थान में लिए देखा जा करने के लिए (क्योंकि यह तर्क है प्रकार std::tuple<int, int>, जो std में है की है), जहां यह पाया की जाएगी। लेकिन, मुझे एक त्रुटि मिलती है। क्या कोई यहां सही दृष्टिकोण की व्याख्या कर सकता है और उपरोक्त कोड क्यों काम नहीं करता है? इस मामले में एडीएल कैसे हो सकता है?

उत्तर

12

समस्या अंततः टेम्पलेट्स है:

std::cout << get<0>(tup) << std::endl; 
//   ~~~~ 

उस बिंदु पर, कंपाइलर यह नहीं जानता कि यह एक ऐसा कार्य है जिसे टी की आवश्यकता है o अभी तक एडीएल का उपयोग करके देखा जाना चाहिए - get सिर्फ एक नाम है।और चूंकि उस नाम से स्वयं कुछ भी नहीं मिला है, इसलिए इसे अज्ञात नाम के रूप में व्याख्या किया जा रहा है जिसके बाद कम से कम। काम करने के लिए इस पाने के लिए आपको कुछ अन्य समारोह टेम्पलेट get दिखाई की जरूरत है:

using std::get; 
std::cout << get<0>(tup) << std::endl; // now, OK 

यहां तक ​​कि अगर यह होता है कुछ भी नहीं:

template <class T> void get(); 

int main() { 
    auto tup = std::make_tuple(1, 2); 
    std::cout << get<0>(tup) << std::endl; 
} 

संरचित बाध्यकारी शब्दों को स्पष्ट रूप से ऊपर get तर्क पर निर्भर देखने का उपयोग कर लगता है, इसलिए यह जरूरत से बचा जाता है get नामित पहले से दिखाई समारोह टेम्पलेट के लिए, [dcl.struct.bind] से:

यू nqualified-आईडीget वर्ग के सदस्य पहुंच देखने से E के दायरे में ऊपर देखा है, और है कि अगर कम से कम एक घोषणा पाता है, प्रारंभकर्ता e.get<i>() है। अन्यथा, प्रारंभकर्ता get<i>(e) है, जहां get संबंधित नामस्थानों में देखा गया है। किसी भी मामले में, get<i> को टेम्पलेट-आईडी के रूप में व्याख्या किया गया है। [नोट: सामान्य अयोग्य लुकअप नहीं किया जाता है। - अंत नोट]

नोट कुंजी है। अगर हमने अयोग्य लुकअप किया था, तो हम बस असफल हो जाएंगे।

+0

बहुत दिलचस्प! मुझे आश्चर्य है कि, इस अपरिभाषित कार्य को शुरू करने से संभावित रूप से किसी अन्य समस्या का कारण बनता है? संघर्ष या पसंद की तरह? – Curious

+0

@ क्रूर अगर यह पसंद किया जा रहा है तो यह होगा। मेरा मतलब है, वास्तव में ऐसा मत करो - मैंने इसे व्याख्यात्मक उद्देश्यों के लिए वहां रखा है। – Barry

+0

हम्म, क्या कोई तरीका है कि मैं एडीएल को मजबूर कर सकता हूं? मैंने 'टेम्पलेट' कीवर्ड की कोशिश की लेकिन निश्चित रूप से यह काम नहीं करता .. – Curious

11

तर्क आश्रित लुकअप for function templates where an explicit template argument is given समान तरीके से काम नहीं करता है।

हालांकि एक समारोह कॉल ADL भले ही साधारण देखने में कुछ भी नहीं, स्पष्ट रूप से निर्धारित टेम्पलेट तर्क के साथ एक समारोह टेम्पलेट के लिए एक समारोह कॉल पाता है के माध्यम से हल किया जा सकता की आवश्यकता साधारण द्वारा पाया टेम्पलेट की एक घोषणा है कि वहाँ देखने

मूल रूप से, वहाँ अयोग्य देखने एक टेम्पलेट समारोह को खोजने के लिए किसी तरह की जरूरत है (अन्यथा, यह में सिंटेक्स त्रुटि एक अज्ञात नाम एक से कम चरित्र के बाद का सामना करने के लिए है)। फिर, एडीएल लात मार सकता है (क्योंकि नाम get तब टेम्पलेट के रूप में जाना जाता है)। Cppreference एक उदाहरण देता है:

namespace N1 { 
    struct S {}; 
    template<int X> void f(S); 
} 
namespace N2 { 
    template<class T> void f(T t); 
} 
void g(N1::S s) { 
    f<3>(s);  // Syntax error (unqualified lookup finds no f) 
    N1::f<3>(s); // OK, qualified lookup finds the template 'f' 
    N2::f<3>(s); // Error: N2::f does not take a non-type parameter 
       //  N1::f is not looked up because ADL only works 
       //    with unqualified names 
    using N2::f; 
    f<3>(s); // OK: Unqualified lookup now finds N2::f 
      //  then ADL kicks in because this name is unqualified 
      //  and finds N1::f 
} 

संरचित बाइंडिंग एक विशेष मामला है, ADL सक्षम के साथ।

निम्नलिखित संदर्भों में ADL-केवल देखने (अर्थात, केवल जुड़े नामस्थान में देखने है) होता है:

  • गैर सदस्य के देखने कार्यों शुरू करते हैं और द्वारा सीमा-के लिए प्रदर्शन किया सिरे लूप अगर सदस्य लुकअप
  • टेम्पलेट त्वरण बिंदु से निर्भर नाम लुकअप विफल रहता है।
  • गैर सदस्य समारोह के देखने टपल की तरह प्रकार के लिए संरचित बाध्यकारी घोषणा द्वारा किया जाता हो

जोर जोड़ा

+0

क्या यह 'std :: cout << टेम्पलेट <0> (tup) << '\ n'' कहने के लिए काम करेगा, या किसी कारण के लिए एक असंबद्ध' टेम्पलेट 'काम नहीं करता है? –

+0

@DanielH ऐसा लगता है * अगर कोई इसे प्रस्तावित करता है तो * काम कर सकता है। यह [इस समय काम नहीं करता] (https://wandbox.org/permlink/dmG6fVeDQwzHvl6q) – Justin

+0

उत्तर के लिए धन्यवाद। मैं दोनों उत्तरों को स्वीकार करना चाहता हूं लेकिन चूंकि दूसरे उत्तर में एक साधारण रिज़ॉल्यूशन तकनीक का सीधा उदाहरण शामिल है। मैं इसे स्वीकार करने जा रहा हूँ। – Curious

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