C ++ 11 make_pair निर्दिष्ट टेम्पलेट मापदंडों के साथ संकलन नहीं करता है


84

मैं सिर्फ g ++ 4.7 (बाद के स्नैपशॉट में से एक) के साथ -std = c ++ 11 सक्षम के साथ खेल रहा था। मैंने अपने कुछ मौजूदा कोड आधार और एक मामले को संकलित करने की कोशिश की जो कुछ हद तक मुझे भ्रमित करता है।

अगर कोई समझा सकता है कि क्या चल रहा है तो मैं सराहना करूंगा।

यहाँ कोड है:

#include <utility>
#include <iostream>
#include <vector>
#include <string>

int main ( )
{
    std::string s = "abc";

    // 1 ok
    std::pair < std::string, int > a = std::make_pair ( s, 7 );

    // 2 error on the next line
    std::pair < std::string, int > b = std::make_pair < std::string, int > ( s, 7 );

    // 3 ok
    std::pair < std::string, int > d = std::pair < std::string, int > ( s, 7 );

    return 0;
}

मैं समझता हूँ कि make_pair है मतलब (1) मामले (अगर मैं प्रकार निर्दिष्ट है, तो मैं भी उपयोग कर सकते हैं (3)) के रूप में प्रयोग की जाने वाली है, लेकिन मुझे समझ नहीं आता क्यों यह इस मामले में नाकाम रहने के है।

सटीक त्रुटि है:

test.cpp: In function ‘int main()’:
    test.cpp:11:83: error: no matching function for call to ‘make_pair(std::string&, int)
    test.cpp:11:83: note: candidate is:
    In file included from /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/utility:72:0,
                 from test.cpp:1:
    /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:274:5:
note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_T1>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
    /gcc4.7/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/bits/stl_pair.h:274:5:
note:   template argument deduction/substitution failed:
    test.cpp:11:83: note:   cannot convert ‘s’ (type ‘std::string {aka std::basic_string<char>}’) to type ‘std::basic_string<char>&&’

फिर, यहाँ सवाल सिर्फ "क्या चल रहा है?" मुझे पता है कि मैं टेम्पलेट विनिर्देशन को हटाकर समस्या को ठीक कर सकता हूं, लेकिन मैं केवल यह जानना चाहता हूं कि कवर के तहत यहां क्या विफल हो रहा है।

  • g ++ 4.4 इस कोड को बिना किसी समस्या के संकलित करता है।
  • हटाना -dd = c ++ 11 भी बिना किसी समस्या के कोड के साथ संकलित करता है।

6
एक उत्कृष्ट प्रश्न। फिर भी C ++ 11 में सूक्ष्म ब्रेकिंग परिवर्तन का एक और उदाहरण, निर्माण में ब्रेकिंग परिवर्तन केstd::vector समान है । कम से कम यह एक संकलक त्रुटि उत्पन्न करता है और शब्दार्थ में एक मौन परिवर्तन नहीं।
जेम्स मैकनेलिस

1
अगर मेरे पास एक पूर्णांक चर है i। मैं i और एक अन्य ऑब्जेक्ट के साथ जोड़ी बनाना चाहता हूं। मुझे वास्तव में मेकप कैसे कहा जाना चाहिए। 1) मेक_पेयर <* i, obj> 2) int && j = i; make_pair <j, obj>? दोनों काम नहीं कर रहे हैं। इसे करने का सही तरीका क्या है?
PHcoDer

जवाबों:


135

यह std::make_pairउपयोग करने का इरादा नहीं है; आप स्पष्ट रूप से टेम्पलेट तर्कों को निर्दिष्ट करने वाले नहीं हैं।

C ++ 11 std::make_pairदो तर्क लेता है, प्रकार के T&&और U&&, जहां Tऔर Uटेम्पलेट प्रकार पैरामीटर हैं। प्रभावी रूप से, यह इस तरह दिखता है (वापसी प्रकार की अनदेखी):

template <typename T, typename U>
[return type] make_pair(T&& argT, U&& argU);

जब आप कॉल std::make_pairऔर स्पष्ट रूप से टेम्पलेट प्रकार के तर्क निर्दिष्ट करते हैं, तो कोई तर्क कटौती नहीं होती है। इसके बजाय, प्रकार के तर्कों को सीधे टेम्पलेट घोषणा में प्रतिस्थापित किया जाता है, उपज:

[return type] make_pair(std::string&& argT, int&& argU);

ध्यान दें कि ये दोनों प्रकार के पैरामीटर संदर्भ संदर्भ हैं। इस प्रकार, वे केवल प्रतिद्वंद्वियों से बंध सकते हैं। यह दूसरे तर्क के लिए कोई समस्या नहीं है जिसे आप पास करते हैं 7, क्योंकि यह एक अभिव्यक्ति है। sहालाँकि, एक अंतराल अभिव्यक्ति है (यह एक अस्थायी नहीं है और इसे स्थानांतरित नहीं किया जा रहा है)। इसका मतलब है कि फ़ंक्शन टेम्प्लेट आपके तर्कों का मेल नहीं है, यही वजह है कि आपको त्रुटि मिलती है।

तो, यह क्यों काम करता है जब आप स्पष्ट रूप से निर्दिष्ट नहीं करते हैं Tऔर Uटेम्पलेट तर्क सूची में क्या हैं? संक्षेप में, rvalue संदर्भ पैरामीटर टेम्पलेट्स में विशेष हैं। रेफरेंस कोलैप्सिंग नामक भाषा सुविधा के एक हिस्से के कारण A&&, प्रकार का एक रेवल्यू रेफरेंस पैरामीटर , जहां Aएक टेम्प्लेट टाइप पैरामीटर है, किसी भी प्रकार से बाँध सकता है A

इससे कोई फर्क नहीं पड़ता है कि क्या Aएक लवल्यू, एक प्रतिद्वंद्विता, कांस्टेबल-योग्य, वाष्पशील-योग्य या अयोग्य है, A&&उस वस्तु को बाँध सकता है (फिर से, यदि और केवल अगर Aखुद एक टेम्पलेट पैरामीटर है)।

आपके उदाहरण में, हम कॉल करते हैं:

make_pair(s, 7)

यहाँ, sप्रकार का एक अंतराल है std::stringऔर प्रकार 7का एक अंतराल है int। चूंकि आप फ़ंक्शन टेम्प्लेट के लिए टेम्पलेट तर्कों को निर्दिष्ट नहीं करते हैं, इसलिए तर्क तर्क कटौती यह पता लगाने के लिए की जाती है कि तर्क क्या हैं।

बांधने के लिए s, एक लैवल्यू, टू T&&, कंपाइलर के प्रकार का तर्क देते हुए, Tहोने के लिए कटौती करता है । हालांकि, संदर्भों का कोई संदर्भ नहीं है, इसलिए यह "डबल संदर्भ" बनने के लिए ढह जाता है । एक मैच है।std::string&std::string& &&std::string&s

यह बांधने के 7लिए सरल है U&&: संकलक घटने के Uलिए int, प्रकार के एक पैरामीटर का उत्पादन कर सकता है int&&, जो सफलतापूर्वक बांधता है 7क्योंकि यह एक प्रतिद्वंद्विता है।

इन नई भाषा सुविधाओं के साथ बहुत सारी सूक्ष्मताएं हैं, लेकिन यदि आप एक सरल नियम का पालन करते हैं, तो यह बहुत आसान है:

यदि किसी टेम्पलेट तर्क को फ़ंक्शन तर्क से घटाया जा सकता है, तो उसे काट दें। जब तक आप पूरी तरह से स्पष्ट रूप से तर्क न दें।

संकलक को कड़ी मेहनत करने दें, और 99.9% समय यह वही होगा जो आप वैसे भी चाहते थे। जब आप ऐसा नहीं चाहते हैं, तो आपको आमतौर पर एक संकलन त्रुटि मिलेगी जो पहचानना और ठीक करना आसान है।


6
यह बहुत अच्छी और व्यापक व्याख्या है। धन्यवाद!
vmpstr

1
@ नाम - क्या वह "एक साधारण नियम" है जो किसी अन्य लेख या उत्तर से मुझे पढ़ना चाहिए?
माइकल बूर

4
@MichaelBurr: नहीं, मैंने अभी-अभी बनाया है। :-) तो, मुझे आशा है कि यह सच है! मुझे लगता है कि यह सच है ... यह नियम मेरे लिए हर समय बहुत काम करता है।
जेम्स मैकनेलिस

1
@ नाम: धन्यवाद। इसके चारों ओर 'उद्धरण बॉक्स' ने मुझे लगता है कि यह मूल रूप से कहीं और लिखा गया हो सकता है। यह उत्तर वास्तव में जानकारीपूर्ण था, और मैं सिर्फ यह सुनिश्चित करना चाहता था कि मैं कहीं और कुछ याद नहीं कर रहा था।
माइकल बूर

2
क्या यह टुपल्स पर भी लागू होता है?
फेर्रुकियो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.