নির্দিষ্ট টেম্পলেট প্যারামিটারগুলির সাথে সি ++ 11 মেক_যুদ্ধ সংকলন করে না


85

আমি সবেমাত্র 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 কোনও সমস্যা ছাড়াই এই কোডটি সংকলন করে।
  • -Std = c ++ 11 মুছে ফেলাও কোনও সমস্যা ছাড়াই কোড সহ কম্পাইল করে।

6
একটি দুর্দান্ত প্রশ্ন। তবুও নির্মাণের ব্রেকিং পরিবর্তনেরstd::vector অনুরূপ সি ++ 11 এ সূক্ষ্ম ব্রেকিং পরিবর্তনের আরও একটি উদাহরণ । কমপক্ষে এটি একটি সংকলক ত্রুটি দেয় এবং শব্দার্থবিজ্ঞানের নীরব পরিবর্তন নয়।
জেমস ম্যাকনেলিস

4
আমার যদি একটি পূর্ণসংখ্যার পরিবর্তনশীল থাকে i। আমি এবং অন্য একটি অবজেক্টের সাথে জুটি তৈরি করতে চাই। আমি ঠিক কিভাবে মেকপেইয়ার কল করা উচিত। 1) মেক_ পেয়ার <* i, আপত্তি> 2) ইনট && j = i; Make_pair <জে, আপত্তি>? দুজনেই কাজ করছে না। এটি করার সঠিক উপায় কী?
PHcoDer

উত্তর:


136

এইভাবে হয় না std::make_pair ব্যবহারের উদ্দেশ্যে হয় ; আপনি স্পষ্টভাবে টেম্পলেট আর্গুমেন্ট নির্দিষ্ট করার কথা নয়।

সি ++ 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তর্কটি পাস করেন এটি এটি কোনও সমস্যা নয় , কারণ এটি একটি মূল মূল্য expression sতবে এটি একটি মূল্যবান অভিব্যক্তি (এটি কোনও অস্থায়ী নয় এবং এটি সরানো হচ্ছে না)। এর অর্থ ফাংশন টেমপ্লেটটি আপনার যুক্তিগুলির সাথে কোনও মিল নয়, যার কারণে আপনি ত্রুটি পান।

সুতরাং, আপনি যখন স্পষ্টভাবে নির্দিষ্ট করে না Tএবং Uটেম্পলেট যুক্তির তালিকায় রয়েছেন তখন কেন এটি কাজ করবে ? সংক্ষেপে, মূল্য সংক্রান্ত রেফারেন্স প্যারামিটারগুলি টেমপ্লেটগুলিতে বিশেষ। রেফারেন্স ভেঙে যাওয়া নামক একটি ভাষার বৈশিষ্ট্যটির কারণে , কোনও ধরণের রেভ্যালু রেফারেন্স প্যারামিটার A&&, যেখানে Aএকটি টেম্পলেট টাইপ প্যারামিটার রয়েছে, যে কোনও প্রকারের সাথে আবদ্ধ হতে পারে A

এটি কোনও Aমূল্য নয়, একটি মূল্যবান, মূল্যবান, কনস্ট-কোয়ালিটিড, অস্থির-যোগ্য, বা অযোগ্য, কোনও একটি A&&সেই বস্তুর সাথে আবদ্ধ হতে পারে (আবার, যদি এবং কেবল যদিA এটি একটি টেম্পলেট প্যারামিটার হয়)।

আপনার উদাহরণে, আমরা কল করি:

make_pair(s, 7)

এখানে, sটাইপের একটি মূল্য রয়েছে std::stringএবং 7এটি টাইপের একটি মূল্যমান int। যেহেতু আপনি ফাংশন টেম্পলেটটির জন্য টেম্পলেট আর্গুমেন্টগুলি নির্দিষ্ট করেন না, তাই আর্গুমেন্টগুলি কী তা নির্ধারণ করার জন্য টেমপ্লেট আর্গুমেন্ট ছাড় দেওয়া হয়।

বাঁধাই করার s, একটি lvalue, এর T&&, কম্পাইলার deduces Tহতে std::string&, টাইপ একজন যুক্তি ফলনশীল std::string& &&। রেফারেন্সের কোনও রেফারেন্স নেই, যদিও, তাই এই "ডাবল রেফারেন্স" হয়ে যায় std::string&sএকটি ম্যাচ।

এটা তোলে এর বাধতে সহজ 7করতে U&&: কম্পাইলার অনুমান করতে পারেন Uহতে int, টাইপ একটি প্যারামিটার ফলনশীল int&&, যা সফলভাবে binds 7কারণ এটি একটি rvalue হয়।

এই নতুন ভাষার বৈশিষ্ট্যগুলির সাথে প্রচুর সূক্ষ্মতা রয়েছে তবে আপনি যদি একটি সাধারণ নিয়ম অনুসরণ করেন তবে এটি বেশ সহজ:

যদি কোনও টেম্পলেট আর্গুমেন্টটি ফাংশন আর্গুমেন্টগুলি থেকে বাদ দেওয়া যায়, তবে এটি কেটে নেওয়া উচিত। আপনার সম্পূর্ণরূপে প্রয়োজন না হলে সুস্পষ্ট যুক্তি সরবরাহ করবেন না।

সংকলকটি কঠোর পরিশ্রম করতে দিন এবং 99.9% সময়ের মধ্যে আপনি যা যা চান ঠিক তেমনই হবে। আপনি যা চেয়েছিলেন তা না হলে আপনি সাধারণত একটি সংকলন ত্রুটি পাবেন যা সনাক্ত করা এবং ঠিক করা সহজ।


6
এটি একটি খুব ভাল এবং ব্যাপক ব্যাখ্যা। ধন্যবাদ!
ভিএমপিস্ট্র 1

4
@ জেমস - "নিখুঁত নিয়ম" কি অন্য কোনও নিবন্ধ বা উত্তর থেকে আমার পড়া উচিত?
মাইকেল বুড়

4
@ মিশেলবার: নাহ, আমি এখনই এটি তৈরি করেছি। :-) সুতরাং, আমি আশা করি এটি সত্য! আমি মনে করি এটি সত্য ... এই নিয়মটি আমার জন্য পুরোপুরি কার্যকর হয়।
জেমস ম্যাকনেলিস

4
@ জেমস: ধন্যবাদ এর চারপাশের 'উদ্ধৃতি বাক্স' আমাকে ভাবতে বাধ্য করেছিল যে এটি সম্ভবত অন্য কোথাও লেখা হয়েছিল। এই উত্তরটি সত্যই তথ্যবহুল ছিল এবং আমি কেবল এটি নিশ্চিত করতে চেয়েছিলাম যে আমি অন্য কোথাও মিস করছি না।
মাইকেল বুড়

4
এটি কি টিপলগুলিতেও প্রযোজ্য?
ফেররুচিয়াও
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.