"আর্গুমেন্ট-ডিপেন্ডেন্ট লুকআপ" (ওরফে এডিএল, বা "কোনিগ লুকআপ") কী?


176

যুক্তি নির্ভর নির্ভরতা কী সম্পর্কে কিছু ভাল ব্যাখ্যা কী? অনেকে এটিকে কোয়েনিগ লুকআপও বলে থাকেন।

সাধারণত আমি জানতে চাই:

  • কেন এটি একটি ভাল জিনিস?
  • কেন এটা খারাপ জিনিস?
  • এটা কিভাবে কাজ করে?




উত্তর:


223

কোইনিগ লুকআপ বা তর্ক নির্ভরতা অবলম্বন বর্ণনামূলকভাবে বর্ণনা করে যে সি ++ তে সংকলক দ্বারা কীভাবে অযোগ্য নামগুলি সন্ধান করা হয়।

সি ++ 11 স্ট্যান্ডার্ড § 3.4.2 / 1 বলেছেন:

যখন কোনও ফাংশন কলের (5.2.2) পোস্টফিক্স-এক্সপ্রেশনটি একটি অযোগ্য-আইডি হয়, তখন সাধারণ অসমর্থিত অনুসন্ধানের (3.4.1) সময় বিবেচনা করা হয়নি এমন অন্যান্য নেমস্পেসগুলি অনুসন্ধান করা যেতে পারে এবং সেই নামের জায়গাগুলিতে, নেমস্পেস-স্কোপ বন্ধু ফাংশন ঘোষণা ( ১১.৩) অন্যথায় দৃশ্যমান নয় এমনটি পাওয়া যেতে পারে। অনুসন্ধানে এই পরিবর্তনগুলি আর্গুমেন্টের ধরণের (এবং টেমপ্লেট টেম্পলেট আর্গুমেন্টগুলির জন্য, টেমপ্লেট আর্গুমেন্টের নামের জায়গার উপর) নির্ভর করে।

সহজ কথায় নিকোলাই জোসুটিস 1 বলেছেন :

ফাংশনের নেমস্পেসে যদি এক বা একাধিক আর্গুমেন্টের ধরণ সংজ্ঞায়িত করা হয় তবে আপনাকে ফাংশনগুলির জন্য নেমস্পেসের যোগ্যতা অর্জন করতে হবে না।

একটি সাধারণ কোড উদাহরণ:

namespace MyNamespace
{
    class MyClass {};
    void doSomething(MyClass);
}

MyNamespace::MyClass obj; // global object


int main()
{
    doSomething(obj); // Works Fine - MyNamespace::doSomething() is called.
}

উপরের উদাহরণে তন্ন তন্ন একটি আছে using-declaration অথবা একটি using-directive কিন্তু এখনও কম্পাইলার সঠিকভাবে অযোগ্য নাম চিহ্নিত doSomething()ফাংশন নামস্থান ঘোষণা যেমন MyNamespaceপ্রয়োগের দ্বারা Koenig লুকআপ

এটা কিভাবে কাজ করে?

অ্যালগরিদম কম্পাইলারকে কেবল স্থানীয় সুযোগের দিকে নজর না দিয়ে আর্গুমেন্টের টাইপযুক্ত নেমস্পেসগুলি দেখতে বলে। সুতরাং, উপরের কোডে, সংকলকটি আবিষ্কার করে যে বস্তুটি obj, যা ফাংশনটির আর্গুমেন্ট doSomething(), নাম স্পেসের সাথে সম্পর্কিত MyNamespace। সুতরাং, এটি ঘোষণাপত্রটি সনাক্ত করতে সেই নামস্থানটি দেখছে doSomething()

কোয়েনিগ দেখার সুবিধা কী?

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

কেন কোনিগের খোঁজ নিয়ে সমালোচনা?

কোয়েনিগ লুকের উপর অতিরিক্ত নির্ভরতা অর্থপূর্ণ সমস্যার কারণ হতে পারে এবং কখনও কখনও প্রোগ্রামারকে রক্ষা করতে পারে।

উদাহরণটি বিবেচনা করুন std::swap, যা দুটি মান অদলবদল করার জন্য একটি আদর্শ গ্রন্থাগার অ্যালগরিদম। কোনিগ লুকআপের সাথে এই অ্যালগরিদমটি ব্যবহার করার সময় কাউকে সতর্ক থাকতে হবে কারণ:

std::swap(obj1,obj2);

এর মতো আচরণটি নাও দেখাতে পারে:

using std::swap;
swap(obj1, obj2);

এডিএল দিয়ে, swapফাংশনের কোন সংস্করণটি কল হয় এটি আর্গুমেন্টের পাস করা যুক্তির নামের জায়গার উপর নির্ভর করবে।

একটি নামস্থান অস্তিত্ব থাকে Aএবং যদি A::obj1, A::obj2& A::swap()অস্তিত্ব তারপর দ্বিতীয় উদাহরণ একটি কল পরিণাম ডেকে আনবে A::swap(), যা কি ব্যবহারকারী চেয়েছিলেন নাও হতে পারে।

তদ্ব্যতীত, যদি কোনও কারণে উভয় কারণে A::swap(A::MyClass&, A::MyClass&)এবং std::swap(A::MyClass&, A::MyClass&)সংজ্ঞায়িত হয় তবে প্রথম উদাহরণটি কল করবে std::swap(A::MyClass&, A::MyClass&)তবে দ্বিতীয়টি সংকলন করবে না কারণ swap(obj1, obj2)এটি অস্পষ্ট।

তুচ্ছ বস্তু:

কেন এটি "কোনিগ লুকআপ" বলা হয়?

কারণ এটি প্রাক্তন এটিএন্ডটি এবং বেল ল্যাবস গবেষক এবং প্রোগ্রামার, অ্যান্ড্রু কোয়েনিং তৈরি করেছিলেন

আরও পড়া:


1 জোসেট্টিসের বই, দ্য সি ++ স্ট্যান্ডার্ড লাইব্রেরি: একটি টিউটোরিয়াল এবং রেফারেন্সে কোনেইগ লুকের সংজ্ঞাটি সংজ্ঞায়িত হয়েছে।


11
@ অলোকস্যাভ: উত্তরের জন্য +1, তবে ট্রিভিয়াটি সঠিক নয়। কোয়েনিগ এডিএল আবিষ্কার করেন নি, যেমন তিনি এখানে স্বীকার করেছেন :)
কিংবদন্তি 2 কে

20
কোয়েনিগ অ্যালগোরিদমের সমালোচনার উদাহরণটি কোয়েনিগ অনুসন্ধানের "বৈশিষ্ট্য" হিসাবে বিবেচিত হতে পারে যতটা "কন" হিসাবে দেখা যায়। এসডিডি :: অদলবদল () এরকমভাবে ব্যবহার করা একটি প্রচলিত প্রথা: আরও বিশেষায়িত সংস্করণ এ :: সোয়াপ () সরবরাহ না করা হলে 'স্ট্যান্ড :: সোয়াপ () ব্যবহার করে' সরবরাহ করুন। যদি এ :: অদলবদল () এর একটি বিশেষ সংস্করণ উপলভ্য থাকে তবে আমরা নরমল চাইব যে সেটিকে কল করা উচিত। এটি অদলবদল () কলটির জন্য আরও উদারতা সরবরাহ করে, যেহেতু আমরা সংকলন এবং কাজ করার জন্য কলটিতে বিশ্বাস করতে পারি, তবে আমরা যদি আরও একটি বিশেষ সংস্করণ ব্যবহার করতে পারি তবে এটি বিশ্বাস করতে পারি।
অ্যান্টনি হল

6
@ অ্যানথ্রন্ড এটি আরও আছে। আপনার সাথে std::swapআসলে এটি করতে হবে যেহেতু একমাত্র বিকল্প std::swapহ'ল আপনার Aশ্রেণীর জন্য টেম্পলেট ফাংশন স্পষ্ট স্পেশালাইজেশন যুক্ত করা। তবুও যদি আপনার Aশ্রেণি নিজেই একটি টেম্পলেট হয় তবে এটি স্পষ্টত বিশেষত্বের চেয়ে আংশিক বিশেষত্ব হবে। এবং টেম্পলেট ফাংশনটির আংশিক বিশেষত্ব অনুমোদিত নয়। এর ওভারলোড যুক্ত করা std::swapবিকল্প হবে তবে এটি স্পষ্টভাবে নিষিদ্ধ করা হয়েছে (আপনি stdনামের জায়গাতে জিনিস যোগ করতে পারেন না )। সুতরাং ADL এর একমাত্র উপায় std::swap
আদম বদুরা

1
আমি "কোয়েঞ্জ লুকিংয়ের সুবিধা" এর অধীনে ওভারলোডেড অপারেটরগুলির একটি উল্লেখ দেখতে আশা করব। উদাহরণটি std::swap()কিছুটা পিছনের দিকে মনে হচ্ছে। আমি সমস্যা না যখন আশা std::swap(), টাইপ জমিদার নির্দিষ্ট বদলে নির্বাচিত হয় A::swap()। উদাহরণটি std::swap(A::MyClass&, A::MyClass&)বিভ্রান্তিকর বলে মনে হচ্ছে। যেহেতু stdকখনও কোনও ব্যবহারকারীর জন্য নির্দিষ্ট ওভারলোড না থাকায় আমি মনে করি এটি দুর্দান্ত উদাহরণ নয়।
আরভিড

1
@আসামারস ... আর? আমরা সকলেই দেখতে পাই যে ফাংশনটি কখনই সংজ্ঞায়িত হয়নি। আপনার ত্রুটি বার্তা প্রমাণ করে যে এটি কার্যকর হয়েছে, কারণ এটি সন্ধান করছে MyNamespace::doSomething, কেবল নয় ::doSomething
তহবিল মনিকার লসুইট

69

Koenig লুকআপ সালে একটি ফাংশন তার নামস্থান উল্লেখ না করে বলা হয়, তাহলে একটি ফাংশন নাম এছাড়াও নামস্থান (গুলি) যা যুক্তি (গুলি) ধরণ সংজ্ঞায়িত করা হয় অনুসন্ধান করেছি। এজন্য এটি সংক্ষেপে এডিএল হিসাবে যুক্তি-নির্ভরশীল নাম লুকআপ নামেও পরিচিত ।

এটি কোনিগ লুকআপের কারণে, আমরা এটি লিখতে পারি:

std::cout << "Hello World!" << "\n";

অন্যথায়, আমাদের লিখতে হবে:

std::operator<<(std::operator<<(std::cout, "Hello World!"), "\n");

যা সত্যিই অনেক বেশি টাইপিং এবং কোডটি দেখতে সত্যিই কুৎসিত দেখাচ্ছে!

অন্য কথায়, কোনিগ লুকআপের অনুপস্থিতিতে, এমনকি একটি হ্যালো ওয়ার্ল্ড প্রোগ্রাম জটিল দেখায়।


12
প্ররোচিত উদাহরণ।
অ্যান্টনি হল

10
@ অ্যাডামবাডুরা: দয়া করে নোট করুন যে std::coutএটি ফাংশনটির জন্য একটি যুক্তি, যা এডিএল সক্ষম করতে যথেষ্ট। আপনি কি তা খেয়াল করেছেন?
নওয়াজ

1
@ মিঃ আপনার প্রশ্নের দীর্ঘ উত্তর দরকার যা এই জায়গাতে সরবরাহ করা যায় না। সুতরাং আমি কেবল আপনাকে যেমন বিষয়গুলিতে পড়তে পরামর্শ দিতে পারি: ১) এর স্বাক্ষর ostream<<(এটি কী আর্গুমেন্ট হিসাবে গ্রহণ করে এবং এটি কী ফিরে আসে) হিসাবে। 2) পুরোপুরি যোগ্য নাম (যেমন std::vectorবা std::operator<<)। 3) আর্গুমেন্ট ডিপেন্ডেন্ট লুকআপের আরও বিশদ অধ্যয়ন।
নওয়াজ

2
@ ওয়ার্ল্ড এসেন্ডার: হ্যাঁ, আপনি ঠিক বলেছেন। std::endlযুক্তি হিসাবে গ্রহণ করতে পারে যে ফাংশন , আসলে একটি সদস্য ফাংশন। যাইহোক, আমি যদি এর "\n"পরিবর্তে ব্যবহার করি std::endlতবে আমার উত্তরটি সঠিক। মন্তব্যের জন্য ধন্যবাদ.
নওয়াজ

2
@Destructor: যেহেতু আকারে একটি ফাংশন কল f(a,b)পূজা একটি বিনামূল্যে ফাংশন। সুতরাং ক্ষেত্রে std::operator<<(std::cout, std::endl);, এই জাতীয় ফাংশন নেই যা std::endlদ্বিতীয় যুক্তি হিসাবে গ্রহণ করে । এটি সদস্য ফাংশন যা std::endlযুক্তি হিসাবে গ্রহণ করে এবং যার জন্য আপনাকে লিখতে হবে std::cout.operator<<(std::endl);। এবং যেহেতু একটি নিখরচায় ফাংশন রয়েছে যা char const*দ্বিতীয় তর্ক হিসাবে "\n"কাজ করে; '\n'পাশাপাশি কাজ করবে।
নওয়াজ

30

হতে পারে কেন এটি দিয়ে শুরু করা ভাল এবং কেবল তারপরে কীভাবে চলে যান।

যখন নেমস্পেসগুলি চালু করা হয়েছিল, তখন ধারণাটি ছিল যে সমস্ত কিছু নেমস্পেসে সংজ্ঞায়িত করা উচিত, যাতে পৃথক গ্রন্থাগারগুলি একে অপরের সাথে হস্তক্ষেপ না করে। তবে এটি অপারেটরদের সাথে একটি সমস্যা চালু করেছে। নিম্নলিখিত কোডে উদাহরণস্বরূপ দেখুন:

namespace N
{
  class X {};
  void f(X);
  X& operator++(X&);
}

int main()
{
  // define an object of type X
  N::X x;

  // apply f to it
  N::f(x);

  // apply operator++ to it
  ???
}

অবশ্যই আপনি লিখতে পারতেন N::operator++(x), তবে এটি অপারেটর ওভারলোডিংয়ের পুরো পয়েন্টকে পরাস্ত করতে পারে। অতএব এমন একটি সমাধান খুঁজে বের করতে হয়েছিল যা সংস্থাপকটি operator++(X&)এটির সুযোগ না থাকা সত্ত্বেও এটি সন্ধান করতে দেয়। অন্যদিকে, এটি এখনও অন্য কোনও সন্ধান করা উচিত নয়operator++ অন্য কোনও সম্পর্কিত, সম্পর্কিত সম্পর্কহীন, যা কলটিকে দ্বিধাগ্রস্থ করতে পারে তার মধ্যে অন্য সংজ্ঞা পাওয়া (এই সাধারণ উদাহরণে আপনি অস্পষ্টতা পাবেন না, তবে আরও জটিল উদাহরণে, আপনি সম্ভবত)) সমাধানটি আর্গুমেন্ট ডিপেন্ডেন্ট লুকআপ (এডিএল) বলা হয়েছিল, কারণ অনুসন্ধানটি আর্গুমেন্টের উপর নির্ভর করে (আরও সঠিকভাবে যুক্তির ধরণে)। যেহেতু স্কিমটি অ্যান্ড্রু আর কোয়েনিগ আবিষ্কার করেছিলেন, তাই এটি প্রায়শই কোয়েনিগ লুকআপও বলা হয়।

কৌতুকটি হ'ল ফাংশন কলগুলির জন্য, সাধারণ নাম অনুসন্ধানের পাশাপাশি (যা ব্যবহারের বিন্দুতে স্কোপগুলিতে নামগুলি খুঁজে পায়), ফাংশনে প্রদত্ত যে কোনও আর্গুমেন্টের ধরণের স্কোপগুলিতে একটি দ্বিতীয় অনুসন্ধান করা হয়। সুতরাং উপরোক্ত উদাহরণের, যদি আপনি লিখতে x++প্রধান, এটা জন্য দেখায় operator++না শুধুমাত্র বিশ্বব্যাপী সুযোগ কিন্তু অতিরিক্ত সুযোগ যেখানে ধরনের x, N::X, সংজ্ঞায়িত করা হয়, অর্থাৎ namespace N। এবং সেখানে এটি একটি মিল খুঁজে পেয়েছে operator++এবং তাই x++কেবল কাজ করে। operator++অন্য নাম-স্পেসে সংজ্ঞায়িত আরেকটি , বলুন N2, তবে খুঁজে পাওয়া যাবে না। যেহেতু এডিএল নামস্থানগুলিতে সীমাবদ্ধ নয়, আপনি ভিতরে f(x)পরিবর্তে ব্যবহার করতে পারেন ।N::f(x)main()


ধন্যবাদ! বাস্তবে কখনও বুঝতে পারিনি কেন এটি ছিল!
user965369

20

আমার মতে এটি সম্পর্কে সমস্ত কিছুই ভাল নয়। সংকলক বিক্রেতারা সহ লোকেরা এর মাঝে মাঝে দুর্ভাগ্যজনক আচরণের কারণে এটি অপমান করে চলেছে।

সিএড ++ 11-এ রেঞ্জের লুপের একটি বড় ওভারহোলের জন্য এডিএল দায়বদ্ধ। এডিএল কখনও কখনও অনিচ্ছাকৃত প্রভাব ফেলতে পারে তা বুঝতে, বিবেচনা করুন যে আর্গুমেন্টগুলি সংজ্ঞায়িত করা হয়েছে কেবল সেই স্থানের ক্ষেত্রগুলিকেই নয়, সেই যুক্তিগুলির প্যারামিটার ধরণের পয়েন্টার ধরণের / পয়েন্টি ধরণের পয়েন্টার ধরণের পরামিতিগুলি , এবং তাই আরও অনেক কিছু।

বুস্ট ব্যবহার করে একটি উদাহরণ

std::vector<boost::shared_ptr<int>> v;
auto x = begin(v);

ব্যবহারকারী বুস্ট.রেঞ্জ লাইব্রেরি ব্যবহার করলে এটি একটি দ্ব্যর্থহীনতার ফলস্বরূপ, কারণ উভয়ই std::beginপাওয়া যায় (ব্যবহার করে ADL দ্বারা std::vector) এবং boost::beginপাওয়া যায় (ADL ব্যবহার করে boost::shared_ptr)।


প্রথম স্থানে টেমপ্লেট আর্গুমেন্ট বিবেচনা করে কী লাভ তা আমি সবসময়ই ভেবেছি।
ডেনিস জিকিফুজ

এডিএলটি কেবল অপারেটরদের জন্যই প্রস্তাবিত এবং অন্য ফাংশনগুলির জন্য স্পেসিফিকালি নেমস্পেসগুলি লেখার জন্য এটির পরামর্শ দেওয়া কি ন্যায়সঙ্গত?
বালকি

এটি কি আর্গুমেন্টের বেস ক্লাসের নেমস্পেসগুলি বিবেচনা করে? (এটি অবশ্যই হয় তবে তা পাগল হবে)।
অ্যালেক্স বি

3
কিভাবে ঠিক করবো? স্টাডি :: ব্যবহার শুরু?
পলম

2
@ পলম হ্যাঁ, std::beginনেমস্পেসের অস্পষ্টতা সাফ করে।
নিকোস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.