স্ট্যান্ড :: টাই কীভাবে কাজ করে?


120

আমি এতে std::tieবেশি চিন্তা না করে ব্যবহার করেছি । এটি কাজ করে তাই আমি কেবল এটি গ্রহণ করেছি:

auto test()
{
   int a, b;
   std::tie(a, b) = std::make_tuple(2, 3);
   // a is now 2, b is now 3
   return a + b; // 5
}

কিন্তু এই কালো যাদু কিভাবে কাজ করে? কীভাবে একটি অস্থায়ী std::tieপরিবর্তন দ্বারা তৈরি হয় aএবং b? আমি এটি আরও আকর্ষণীয় মনে করি কারণ এটি একটি লাইব্রেরি বৈশিষ্ট্য, কোনও ভাষা বৈশিষ্ট্য নয়, তাই অবশ্যই এটি এমন একটি বিষয় যা আমরা নিজেরাই প্রয়োগ করতে পারি এবং বুঝতে পারি।

উত্তর:


152

মূল ধারণাটি স্পষ্ট করার জন্য, আসুন এটি আরও বেসিক উদাহরণে কমিয়ে দিন। যদিও std::tieআরও মানগুলি ফাংশন (একটি টিপল) ফিরিয়ে দেওয়ার জন্য দরকারী তবে আমরা এটি কেবলমাত্র একটি মান দিয়ে সূক্ষ্মভাবে বুঝতে পারি:

int a;
std::tie(a) = std::make_tuple(24);
return a; // 24

এগিয়ে যাওয়ার জন্য আমাদের যে বিষয়গুলি জানতে হবে:

  • std::tie রেফারেন্সগুলির একটি দ্বিগুণ গঠন এবং প্রদান করে।
  • std::tuple<int>এবং std::tuple<int&>2 সম্পূর্ণ আলাদা ক্লাস, তাদের মধ্যে কোনও সংযোগ না করে, অন্য যে তারা একই টেম্পলেট থেকে তৈরি হয়েছিল std::tuple,।
  • টিপলের operator=বিভিন্ন ধরণের (তবে একই সংখ্যা) একটি গ্রহণযোগ্য পদার্থ রয়েছে , যেখানে প্রতিটি সদস্যকে স্বতন্ত্রভাবে অর্পণ করা হয় - সিপ্রেফারেন্স থেকে :

    template< class... UTypes >
    tuple& operator=( const tuple<UTypes...>& other );

    (3) আমি জন্য নির্ধারণ std::get<i>(other)করতে std::get<i>(*this)

পরবর্তী পদক্ষেপটি হ'ল সেই ফাংশনগুলি থেকে মুক্তি পাওয়া যা কেবলমাত্র আপনার পথে আসে, তাই আমরা আমাদের কোডটিকে এখানে রূপান্তর করতে পারি:

int a;
std::tuple<int&>{a} = std::tuple<int>{24};
return a; // 24

পরবর্তী পদক্ষেপটি হ'ল এই কাঠামোর ভিতরে ঠিক কী ঘটে তা দেখা। এর জন্য, আমি 2 ধরণের Tবিকল্প std::tuple<int>এবং Trবিকল্পের তৈরি করি std::tuple<int&>, আমাদের ক্রিয়াকলাপের জন্য সর্বনিম্নে নামিয়ে রেখেছি :

struct T { // substituent for std::tuple<int>
    int x;
};

struct Tr { // substituent for std::tuple<int&>
    int& xr;

    auto operator=(const T& other)
    {
       // std::get<I>(*this) = std::get<I>(other);
       xr = other.x;
    }
};

auto foo()
{
    int a;
    Tr{a} = T{24};

    return a; // 24
}

এবং পরিশেষে, আমি কাঠামোগুলি সমস্ত একসাথে মুছে ফেলতে চাই (ভাল, এটি 100% সমতুল্য নয়, তবে এটি আমাদের কাছে যথেষ্ট, এবং এটির অনুমতি দেওয়ার পক্ষে যথেষ্ট স্পষ্ট):

auto foo()
{
    int a;

    { // block substituent for temporary variables

    // Tr{a}
    int& tr_xr = a;

    // T{24}
    int t_x = 24;

    // = (asignement)
    tr_xr = t_x;
    }

    return a; // 24
}

সুতরাং মূলত, std::tie(a)একটি ডেটা সদস্য রেফারেন্স সূচনা করে astd::tuple<int>(24)মান সহ একটি ডেটা সদস্য তৈরি করে 24এবং অ্যাসাইনমেন্টটি প্রথম কাঠামোর মধ্যে ডেটা সদস্যের রেফারেন্সকে 24 বরাদ্দ করে। কিন্তু যেহেতু ডেটা সদস্যটি একটি রেফারেন্সের সাথে আবদ্ধ হয় a, এটি মূলত নির্ধারিত 24হয় a


1
আমার বাগ কী আছে তা হ'ল আমরা একটি অ্যাসাইনমেন্ট অপারেটরকে একটি মূল্যকে কল করছি।
আদম জহরান

ইন এই উত্তর, এটা বলেন যে একটি ধারক একটি রেফারেন্স ধরে না। কেন tupleএকটি রেফারেন্স রাখা যেতে পারে?
nn0p

6
@ nn0p std::tupleকোনও ধারক নয়, কমপক্ষে সি ++ পরিভাষায় নয় std::vector, পছন্দগুলি এবং পছন্দগুলির মতো নয়। উদাহরণস্বরূপ আপনি একটি টিউপল ধরে সাধারণ উপায়ে পুনরাবৃত্তি করতে পারবেন না কারণ এতে বিভিন্ন ধরণের অবজেক্ট রয়েছে।
বলভ

@ অ্যাডাম টাই (x, y) = মেক_ পেয়ার (1,2); আসলে এসটিডি :: টাই (X, Y) .operator = হয়ে (এসটিডি :: make_pair (1, 2)) কেন "একটি rvalue করার নিয়োগ" XD কাজ করে, এটা
জু পিস

30

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

সি ++ 17 এর মাধ্যমে আপনি স্ট্রাকচার্ড বাইন্ডিংসstd::tie যার পক্ষে পক্ষে বেশ স্ক্র্যাচ করতে পারেন । তারা একই কাজ (অবশ্য একই নয় , যদিও আপনি অপেক্ষাকৃত কম অক্ষর বিশিষ্ট টাইপ করতে হবে, কিন্তু তারা একই নেট প্রভাব আছে), এটা পাঠাগারের সমর্থন দরকার নেই, এবং আপনি এছাড়াও , রেফারেন্স নেওয়ার ক্ষমতা আছে যদি হতে হবে তুমি কি চাও.

(দ্রষ্টব্য যে সি +++ এর মধ্যে কনস্ট্রাক্টরগুলি আর্গুমেন্ট ডিসকশন করেন, তাই make_tupleকিছুটা অতিরিক্ত অতিরিক্তও হয়ে উঠেছে))

int a, b;
std::tie(a, b) = std::make_tuple(2, 3);

// C++17
auto  [c, d] = std::make_tuple(4, 5);
auto  [e, f] = std::tuple(6, 7);
std::tuple t(8,9); auto& [g, h] = t; // not possible with std::tie

2
যদি শেষ লাইনটি সংকলিত হয় তবে আমি কিছুটা উদ্বিগ্ন। দেখে মনে হচ্ছে এটি কোনও অস্থায়ী সম্পর্কিত রেফারেন্সকে বাধ্যতামূলক করে যা অবৈধ।
নীড় ফ্রিডম্যান

3
@ নীল এটি হয় একটি মূল্যের রেফারেন্স, বা কনস্ট লভ্যু রেফারেন্স হতে হবে। আপনি একটি মূল্য (অস্থায়ী) এর জন্য মূল্যমানের রেফারেন্সকে আবদ্ধ করতে পারবেন না। যদিও এটি যুগ যুগ ধরে এমএসভিসিতে একটি "এক্সটেনশন" হয়ে আসছে।
নীড় ফ্রিডম্যান

1
সম্ভবত এটি উল্লেখ করার মতোও যে tie, কাঠামোগত বাইন্ডিংগুলি ডিফল্ট-গঠনমূলক নয় এমন ধরণের ক্ষেত্রে এইভাবে ব্যবহার করা যেতে পারে।
ড্যান

5
হ্যাঁ, std::tie()সি ++ 17 এর চেয়ে অনেক কম কার্যকর, যেখানে কাঠামোগত বাইন্ডিংগুলি সাধারণত উচ্চতর হয় তবে এটি এখনও বিদ্যমান (একযোগে নতুনভাবে ঘোষিত নয়) ভেরিয়েবলগুলিকে নির্ধারণ এবং সংক্ষিপ্তভাবে একাধিক ভেরিয়েবল বা অন্য জিনিসগুলিকে অদলবদলের মতো অন্যান্য জিনিসগুলি সহ ব্যবহার করে including রেফারেন্স বরাদ্দ করতে হবে।
আন্ডারস্কোর_দি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.