সি ++ 11 এ "অটো" দিয়ে ছাড়ের সময় ল্যাম্বদা কী ধরণের?


142

আমার ধারণা ছিল যে, ল্যাম্বডা টাইপের একটি ফাংশন পয়েন্টার। আমি যখন নিম্নলিখিত পরীক্ষাটি করেছিলাম তখন আমি এটি ভুল ( ডেমো ) বলে মনে করেছি।

#define LAMBDA [] (int i) -> long { return 0; }
int main ()
{
  long (*pFptr)(int) = LAMBDA;  // ok
  auto pAuto = LAMBDA;  // ok
  assert(typeid(pFptr) == typeid(pAuto));  // assertion fails !
}

উপরের কোডটি কি কোনও বিন্দু অনুপস্থিত? যদি তা না হয় তবে কীওয়ার্ডের typeofসাথে অনুদানের সময় ল্যাম্বডা এক্সপ্রেশনটি autoকী?


8
"ল্যাম্বডা টাইপের একটি ফাংশন পয়েন্টার" - এটি অদক্ষ হবে এবং ল্যাম্বডাসের পুরো পয়েন্টটি মিস করবে।
কনরাড রুডল্ফ

উত্তর:


145

ল্যাম্বডা এক্সপ্রেশনের ধরণটি অনির্ধারিত।

তবে এগুলি সাধারণত ফান্ট্যাকারদের জন্য কেবল সিনট্যাকটিক চিনি। একটি ল্যাম্বদা সরাসরি একটি ফান্টারে অনুবাদ করা হয়। এর অভ্যন্তরের যে []কোনও কিছুই কনস্ট্রাক্টর প্যারামিটার এবং ফান্টর অবজেক্টের সদস্যগুলিতে পরিণত হয় এবং ভিতরে থাকা প্যারামিটারগুলি ()ফান্টাক্টরের জন্য পরামিতিগুলিতে পরিণত হয় operator()

কোনও ল্যাম্বদা যা কোনও ভেরিয়েবল ক্যাপচার করে না (এর অভ্যন্তরে কিছুই নেই []) একটি ফাংশন পয়েন্টারে রূপান্তরিত করা যায় (এমএসভিসি2010 এটি সমর্থন করে না, যদি এটি আপনার সংকলক হয় তবে এই রূপান্তরটি স্ট্যান্ডার্ডের অংশ)।

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


1
MSVC2010 ফাংশন পয়েন্টারে রূপান্তরকে সমর্থন করে না, তবে এমএসভিসি 11 করে। ব্লগস.এমএসএন
ভিসিবি

18
"ফান্ট্যাক্টারের জন্য নিছক সিনট্যাকটিক চিনির জন্য" +1। এটি মনে করে অনেক সম্ভাব্য বিভ্রান্তি এড়ানো যায়।
বেন

4
একটি functor কিছু সঙ্গে operator()মূলত stackoverflow.com/questions/356950/c-functors-and-their-uses
TankorSmash

107

এটি একটি অনন্য নামবিহীন কাঠামো যা ফাংশন কল অপারেটরটিকে ওভারলোড করে। ল্যাম্বদার প্রতিটি ঘটনাই একটি নতুন প্রকারের পরিচয় দেয়।

অ-ক্যাপচারিং ল্যাম্বদার বিশেষ ক্ষেত্রে, কাঠামোর সাথে ফাংশন পয়েন্টারটিতে অন্তর্ভুক্ত রূপান্তর রয়েছে।


2
চমৎকার উত্তর. আমার চেয়ে অনেক বেশি সুনির্দিষ্ট +1 :)
জুলফ

4
ইউনিটটির অংশের জন্য +1, এটি প্রথম এবং যোগ্যতার দিকে মনোযোগ দিয়ে চমকপ্রদ।
ম্যাথিউ এম।

এটি সত্য যে গুরুত্বপূর্ণ তা নয়, তবে কী টাইপটি সত্যই নামবিহীন, বা সংকলনের সময় পর্যন্ত এটি কোনও নাম দেওয়া হয়নি? IOW, কেউ কি আরটিটিআই ব্যবহার করে সংকলকটির নামটি নির্ধারণ করতে পারে?
বেন

3
@ বেন, এটি নামবিহীন এবং সি ++ ভাষার বিষয়ে যতদূর বোঝা যায়, "সংকলক যে নামটি সিদ্ধান্ত নেয় তার নাম" বলে কিছুই নেই। ফলাফলটি type_info::name()বাস্তবায়ন-সংজ্ঞায়িত, সুতরাং এটি কোনও কিছু ফিরিয়ে দিতে পারে। অনুশীলনে, সংকলক লিঙ্কারের খাতিরে প্রকারটির নাম দেবে।
অবাকর

1
ইদানীং যখন এই প্রশ্ন জিজ্ঞেস করলেন, আমি সাধারণত বলে যে ল্যামডা ধরন হয়েছে একটি নাম, কম্পাইলার তা জানেন, এটা ঠিক অকথ্য আছে।
আন্দ্রে কোস্টুর

24

[C++11: 5.1.2/3]: ধরণ ল্যামডা প্রকাশ (এটিও অবসান বস্তুর প্রকার) একটি অনন্য, নামহীন অ ইউনিয়ন শ্রেণী প্রকার - নামক অবসান টাইপ যার বৈশিষ্ট্য নিচে বর্ণনা করা হয় -। এই শ্রেণীর ধরণ কোনও সমষ্টি নয় (8.5.1)। অবসান টাইপ ক্ষুদ্রতম ব্লক সুযোগ, বর্গ সুযোগ, বা নামস্থান সুযোগ যে সংশ্লিষ্ট থাকে ঘোষিত হয় ল্যামডা প্রকাশ[..]

ধারাটি এই ধরণের বিভিন্ন বৈশিষ্ট্য তালিকাতে চলেছে। এখানে কিছু হাইলাইটস রয়েছে:

[C++11: 5.1.2/5]:একটি জন্য অবসান টাইপ ল্যামডা প্রকাশ একটি পাবলিক হয়েছে inlineফাংশন কল অপারেটর (13.5.4) যাদের পরামিতি এবং রিটার্ন টাইপ দ্বারা বর্ণনা করা হয় ল্যামডা প্রকাশ 'র পরামিতি-ঘোষণা-দফা এবং trailing রিটার্ন টাইপ যথাক্রমে। [..]

[C++11: 5.1.2/6]:ল্যাম্বডা-ক্যাপচার ছাড়াই ল্যাম্বডা-এক্সপ্রেশনের জন্য ক্লোজারের ধরণটিতে ক্লোজার টাইপের ফাংশন কল অপারেটরের মতো একই প্যারামিটার এবং রিটার্নের ধরণের বৈশিষ্ট্যযুক্ত একটি সার্বজনীন অ-ভার্চুয়াল নন-স্পষ্ট কনস্ট রূপান্তর ফাংশন রয়েছে। এই রূপান্তর ফাংশনটির মাধ্যমে ফিরে আসা মানটি কোনও ফাংশনের ঠিকানা হবে যা যখন আহ্বান করা হয় তখন ক্লোজার টাইপের ফাংশন কল অপারেটরকে অনুরোধ করার মতোই প্রভাব ফেলবে।

এই চূড়ান্ত উত্তরণের ফলাফলটি হ'ল, যদি আপনি কোনও রূপান্তর ব্যবহার করেন তবে আপনি নির্ধারণ LAMBDAকরতে সক্ষম হবেন pFptr


3
#include <iostream>
#include <typeinfo>

#define LAMBDA [] (int i)->long { return 0l; }
int main ()
{
  long (*pFptr)(int) = LAMBDA;  // ok
  auto pAuto = LAMBDA;  // ok

  std::cout<<typeid( *pAuto ).name() << std::endl;
  std::cout<<typeid( *pFptr ).name() << std::endl;

  std::cout<<typeid( pAuto ).name() << std::endl;
  std::cout<<typeid( pFptr ).name() << std::endl;
}

ফাংশনের ধরণগুলি আসলে একই, তবে ল্যাম্বদা নতুন ধরণের (একটি ফান্টারের মতো) পরিচয় করে।


আপনি যদি ইতিমধ্যে এই পথে চলে যান তবে আমি সিএক্সএক্সএবিবি অবিচ্ছেদ্য পদ্ধতির প্রস্তাব দিচ্ছি । পরিবর্তে, আমি সাধারণত __PRETTY_FUNCTION__হিসাবে হিসাবে ব্যবহার করি template<class T> const char* pretty(T && t) { return __PRETTY_FUNCTION__; }, এবং এটি ভিড় পেতে শুরু করে অতিরিক্ত ছাঁটাই। আমি টেম্পলেট প্রতিস্থাপনে দেখানো পদক্ষেপগুলি দেখতে পছন্দ করি। যদি আপনি নিখোঁজ __PRETTY_FUNCTION__হন তবে এমএসভিসি ইত্যাদির বিকল্প রয়েছে, তবে ফলাফলগুলি সর্বদা একই কারণে সিএক্সএক্সএবিআই প্রয়োজনীয় comp
জন পি

1

এটিও লক্ষ করা উচিত যে ল্যাম্বদা ফাংশন পয়েন্টারটিতে রূপান্তরযোগ্য। তবে টাইপড <> একটি নন-ট্রিভিয়াল অবজেক্ট ফেরত দেয় যা ল্যাম্বডা থেকে জেনেরিক ফাংশন পয়েন্টারের চেয়ে পৃথক হওয়া উচিত। সুতরাং typid <> এর জন্য পরীক্ষাটি একটি বৈধ অনুমান নয়। সাধারণ সি ++ 11 আমাদের টাইপ স্পেসিফিকেশন সম্পর্কে উদ্বিগ্ন হতে চায় না, যদি কোনও প্রদত্ত টাইপ একটি টার্গেটের ধরণে রূপান্তরিত হয় তবে তা সমস্ত ব্যাপার।


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

0

ক্লাসের সদস্য হিসাবে আমি কীভাবে বুস্ট :: বাইন্ড অবজেক্টটি সঞ্চয় করতে পারি এর একটি ব্যবহারিক সমাধান ? , চেষ্টা boost::function<void(int)>বা std::function<void(int)>


1
তবে এর পারফরম্যান্স ব্যয়ের বিষয়ে সচেতন থাকুন (ভার্চুয়াল ফাংশন কলটি প্রতিবার ফাংশনটি বলা হয়) time
হাইকম্যান্ডার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.