'টিউপল' এবং 'টাই' এর মাধ্যমে তুলনা অপারেটরগুলি বাস্তবায়ন করা ভাল ধারণা?


98

(দ্রষ্টব্য: tupleএবং tieবুস্ট বা সি ++ 11 থেকে নেওয়া যেতে পারে))
কেবলমাত্র দুটি উপাদান দিয়ে ছোট ছোট স্ট্রাক্ট লেখার সময় আমি মাঝে মাঝে একটি বেছে নেওয়ার প্রবণতা করি std::pairকারণ সমস্ত গুরুত্বপূর্ণ জিনিস ইতিমধ্যে সেই ডেটাটাইপের জন্য করা হয়েছে যেমন operator<কড়া-দুর্বল-অর্ডার করার জন্য ।
ডাউনসাইডগুলি যদিও বেশ অযথা পরিবর্তনশীল নাম। এমনকি আমি নিজেও এটি তৈরি করে নিলেও typedef, আমি 2 দিন পরে মনে করব না কী firstএবং আসলে কী secondছিল, বিশেষত যদি তারা উভয় একই ধরণের হয়। দু'জনের বেশি সদস্যের পক্ষে এটি আরও খারাপ হয়ে ওঠে, যেমন বাসা বেঁধে দেয় pairmuch
তার জন্য অন্য বিকল্পটি হ'ল কtuple, হয় বুস্ট বা সি ++ 11 থেকে, তবে এটি প্রকৃতপক্ষে কোনও সুন্দর এবং পরিষ্কার দেখাচ্ছে না। সুতরাং আমি প্রয়োজনীয় স্ট্রাক্ট লেখার দিকে ফিরে যাই, প্রয়োজনীয় তুলনা অপারেটরগুলি সহ।
যেহেতু বিশেষত এটি operator<বেশ জটিল হতে পারে, তাই আমি কেবল এইটির জন্য সংজ্ঞায়িত অপারেশনগুলির উপর নির্ভর করে এই পুরো জগাখিচাটি থেকে বিরত থাকার কথা ভেবেছিলাম tuple:

উদাহরণস্বরূপ operator<, কঠোর-দুর্বল-আদেশের জন্য:

bool operator<(MyStruct const& lhs, MyStruct const& rhs){
  return std::tie(lhs.one_member, lhs.another, lhs.yet_more) <
         std::tie(rhs.one_member, rhs.another, rhs.yet_more);
}

( tieএকটি তোলে tupleএর T&পাস আর্গুমেন্ট থেকে রেফারেন্স।)


সম্পাদনা করুন : @ ডেডএমজি থেকে ব্যক্তিগতভাবে উত্তরাধিকার সূত্রে প্রাপ্ত পরামর্শটি tupleখারাপ কিছু নয়, তবে এটি বেশ কিছুটা ত্রুটি পেয়েছে:

  • যদি অপারেটররা মুক্ত-স্থায়ী (সম্ভবত বন্ধুবান্ধব) হয় তবে আমার প্রকাশ্যে উত্তরাধিকার সূত্রে প্রাপ্ত হওয়া দরকার
  • কাস্টিংয়ের সাথে, আমার ফাংশন / অপারেটরগুলি ( operator=বিশেষত) সহজেই বাইপাস করা যায়
  • সঙ্গে tieসমাধান, আমি নির্দিষ্ট সদস্যদের বাইরে চলে যাবে যদি তারা অর্ডার দেওয়ার ব্যাপার না

এই বাস্তবায়নের ক্ষেত্রে কোন ত্রুটি আছে যা আমি বিবেচনা করা দরকার?


4
আমার কাছে পুরোপুরি যুক্তিযুক্ত মনে হচ্ছে ...
iljarn

4
এটি খুব চালাক ধারণা, এমনকি যদি এটি প্যান না করে। আমি এই তদন্ত করতে হবে।
টেম্পলেটটিফাইফ

এটিকে বেশ যুক্তিসঙ্গত মনে হচ্ছে। আমি এখনই ভাবতে পারি যে tieবিট-ফিল্ড সদস্যদের ক্ষেত্রে এটি প্রয়োগ করা যায় না।
ইয়েস উইস্টারিয়া

4
আমি এই ধারনাটি পছন্দ করি! যদি tie(...)কলগুলি বিভিন্ন অপারেটর (=, ==, <, ইত্যাদি) তে সদৃশ হয়ে যায় তবে আপনি একটি ব্যক্তিগত ইনলাইন পদ্ধতি লিখতে make_tuple(...)পারেন এবং তারপরে বিভিন্ন অন্যান্য স্থান থেকে কল return lhs.make_tuple() < rhs.make_tuple();করতে পারেন ( যেমন ফেরত টাইপ থেকে ঘোষণা করার জন্য সেই পদ্ধতিটি মজাদার হতে পারে!)
অ্যালডো

13
@ অ্যালডো: সি +++ এ উদ্ধার! auto tied() const{ return std::tie(the, members, here); }
Xeo

উত্তর:


61

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


17
আমি একটি মামলা যেখানে কল্পনা করতে পারবেন না tuple<>'এর operator<একটি হাতে লেখা এক তুলনায় কোনো ধীর হবে।
iljarn

51
আমি এই একই ধারণাটি একবার পেয়েছি এবং কিছু পরীক্ষা-নিরীক্ষা করেছি। ইতিবাচক দেখতে কম্পাইলার inlined এবং আউট অপ্টিমাইজ অবাক হয়ে সবকিছু সমাবেশ প্রায় হাতে লেখা কোডে অভিন্ন emitting, tuples এবং তথ্যসূত্র সঙ্গে কাজ করতে হচ্ছে।
জোহানেসড

7
@ জোহানেসডি: আমি সেই সাক্ষ্যকে সমর্থন করতে পারি, একবারও এটি করেছি
দেখেছি

এই গ্যারান্টি কি কঠোরভাবে দুর্বল আদেশের ? কীভাবে?
CINCout

5

আমি এই একই সমস্যাটি পেয়েছি এবং আমার সমাধানে c ++ 11 ভ্যারিয়েডিক টেম্পলেট ব্যবহার করে। এখানে কোড আসে:

.H অংশ:

/***
 * Generic lexicographical less than comparator written with variadic templates
 * Usage:
 *   pass a list of arguments with the same type pair-wise, for intance
 *   lexiLessthan(3, 4, true, false, "hello", "world");
 */
bool lexiLessthan();

template<typename T, typename... Args>
bool lexiLessthan(const T &first, const T &second, Args... rest)
{
  if (first != second)
  {
    return first < second;
  }
  else
  {
    return lexiLessthan(rest...);
  }
}

এবং তর্ক ছাড়াই বেস কেসটির জন্য .cpp:

bool lexiLessthan()
{
  return false;
}

এখন আপনার উদাহরণটি হয়ে যায়:

return lexiLessthan(
    lhs.one_member, rhs.one_member, 
    lhs.another, rhs.another, 
    lhs.yet_more, rhs.yet_more
);

আমি এখানে অনুরূপ সমাধান রেখেছি কিন্তু অপারেটরের প্রয়োজন নেই। stackoverflow.com/questions/11312448/...
steviekm3

3

আমার মতে, আপনি এখনও সমাধান হিসাবে একই সমস্যাটি সম্বোধন করছেন না - std::tupleযথা, প্রতিটি সদস্যের পরিবর্তনশীল কত এবং আপনার নাম উভয়ই জানতে হবে, আপনি এটি ফাংশনে দুবার নকল করছেন। আপনি privateউত্তরাধিকার বেছে নিতে পারেন ।

struct somestruct : private std::tuple<...> {
    T& GetSomeVariable() { ... }
    // etc
};

এই পদ্ধতির একটি হল সামান্য একটি জগাখিচুড়ি দিয়ে শুরু করতে এর বিট আরো, কিন্তু আপনি শুধুমাত্র পরিবর্তে প্রত্যেক অপারেটর আপনি জমিদার করতে ইচ্ছুক জন্য প্রতি জায়গায় এক জায়গায় ভেরিয়েবল নাম বজায় রাখার করছি।


4
সুতরাং আমি যেমন ভেরিয়েবলের নামকৃত অ্যাকসেসর ব্যবহার করব T& one_member(){ return std::get<0>(*this); }? তবে কনস্ট এবং নন-কনস্ট্যান্ট সংস্করণের জন্য ওভারলোডগুলি সহ আমার প্রতিটি "সদস্য" এর জন্য আমাকে এমন পদ্ধতি সরবরাহ করার দরকার হবে না?
Xeo

@ শিও আমি প্রকৃত ভেরিয়েবলগুলি তৈরি করার চেয়ে আর কোনও কাজের প্রয়োজন হিসাবে নামকৃত অ্যাক্সেসরগুলি দেখতে পাচ্ছি না। যে কোনও উপায়ে আপনার প্রতিটি ভেরিয়েবলের আলাদা নাম রাখতে হবে। আমি মনে করি কনস্ট্যান্ড / নন-কনস্টের জন্য সদৃশ আছে। তবে আপনি এই সমস্ত কাজের টেমপ্লেট করতে পারেন।
লি লুভিয়ের

1

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

আপনি টিপলের সদস্যদের "নতুন নামকরণ" করতে অ্যাকসেসর তৈরি করতে পারেন।


আমি ওপি'র প্রশ্নটি অর্থ হিসাবে "পড়া আমার ক্লাস প্রয়োগ করছে ' যুক্তিসঙ্গত operator<ব্যবহার করে std::tie?" এই উত্তরটি কীভাবে এই প্রশ্নের সাথে সম্পর্কিত তা আমি বুঝতে পারি না।
iljarn

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