ল্যাম্বদার সি ++ ত্রৈমাসিক কার্য


11

নীচের স্নিপেট কেন সংকলন করে না এমন কোনও ধারণা? এটি একটি ত্রুটির সাথে অভিযোগ করে "ত্রুটি: অপারেশন করে?: বিভিন্ন ধরণের রয়েছে"

  auto lambda1 = [&](T& arg) {
      ...
  };
  auto lambda2 = [&](T& arg) {
      ...
  };
  auto lambda = condition ? lambda1 : lambda2;

উত্তর:


11

পৃথক ল্যাম্বডাস সংকলক দ্বারা বিভিন্ন শ্রেণিতে অনুবাদ করা হয়। উদাহরণস্বরূপ, ল্যাম্বদা 1 এর সংজ্ঞাটি সমান:

class SomeCompilerGeneratedTypeName {
public:
  SomeCompilerGeneratedTypeName(...) { // Capture all the required variables here
  }

  void operator()(T& arg) const {
    // ...
  }

private:
  // All the captured variables here ...
};

অতএব, দুটি পৃথক প্রকার সংকলক দ্বারা উত্পাদিত হয়, যা এর জন্য একটি ধরণের বেমানান হয় causes auto lambda = condition ? lambda1 : lambda2;

নিম্নলিখিত কাজ করবে:

auto lambda = condition ? std::function<void(T&)>(lambda1) : std::function<void(T&)>(lambda2);

উভয় ল্যাম্বডাস প্রকৃতপক্ষে বিভিন্ন ধরণের হাইলাইট করার জন্য, আমরা <typeinfo>স্ট্যান্ডার্ড লাইব্রেরি এবং typeidঅপারেটর থেকে ব্যবহার করতে পারি । ল্যাম্বডাস বহুবিধ প্রকারের নয়, সুতরাং মানটি গ্যারান্টি দেয় যে সংকলনের সময় 'টাইপড' অপারেটরটি মূল্যায়ন করা হয়। এটি দেখায় যে আরটিটিআই অক্ষম থাকলেও নিম্নলিখিত উদাহরণটি বৈধ:

#include <iostream>
#include <typeinfo>

int main()
{
    struct T {

    };

    auto lambda1 = [&](T& arg) {
        return;
    };

    auto lambda2 = [&](T& arg) {
      return;
    };

    std::cout << typeid(lambda1).name() << "/" << typeid(lambda1).hash_code() << std::endl;
    std::cout << typeid(lambda2).name() << "/" << typeid(lambda2).hash_code() << std::endl;

    return 0;
}

প্রোগ্রামটির আউটপুটটি হ'ল (জিসিসি 8.3 সহ, গবোল্টে দেখুন ):

Z4mainEUlRZ4mainE1TE_/7654536205164302515
Z4mainEUlRZ4mainE1TE0_/10614161759544824066

সম্পূর্ণ ত্রুটিটি "ত্রুটি: অপারেশন করে?: বিভিন্ন ধরণের 'এফ (কনস্ট্যান্ড স্টেড :: ভেক্টর <মিন্ট & &, সাইজ_টি, সাইজ_টি) রয়েছে [টি = স্বাক্ষরবিহীন অক্ষরের সাথে; আকার_টি = দীর্ঘ স্বাক্ষরযুক্ত]] :: <লাম্বদা (স্বাক্ষরবিহীন চর & )> 'এবং' এফ (কনস্ট স্ট্যান্ড :: ভেক্টর <মিন্ট & & সাইজ_টি, সাইজ_টি) [টি = স্বাক্ষরবিহীন চর; সাইজ_টি = দীর্ঘ স্বাক্ষরবিহীন]] :: <ল্যাম্বদা (স্বাক্ষরবিহীন চর &)> '", যাতে আমি দেখছি অভিন্ন সব ধরণের ও ফর্ম্যাট।
গরু

1
@ ইয়াকো যেহেতু ল্যাম্বদা নিজের মধ্যে একই স্বাক্ষর রাখে তাই সংকলক এর প্রয়োগের বিশদটি গোপন করতে এবং আরও বোধগম্য ত্রুটি দেওয়ার জন্য আপনাকে উভয় ল্যাম্বডাসের অবস্থান এবং স্বাক্ষর দেয় যা অভিন্ন। তবে শেষ পর্যন্ত তাদের এখনও ব্যাখ্যা করা হয় SomeCompilerGeneratedTypeName1এবংSomeCompilerGeneratedTypeName2
জ্যাটিরিয়ান

1
@ ইয়াকো আমি একটি উদাহরণ যুক্ত করেছি যা উত্তরের সূচনাটি তুলে ধরেছে, আপনি এটি আকর্ষণীয় মনে করতে পারেন
জ্যাটিরিয়ান

12

কৌতূহলজনকভাবে, যদি ল্যাম্বডাস ক্যাপচার-কম হয় তবে অপারেটর +ট্রিক নিয়োগ দেওয়া যেতে পারে:

auto lambda1 = [](int arg) { ... };
auto lambda2 = [](int arg) { ... };

auto lambda = condition ? +lambda1 : +lambda2; // This compiles!
lambda(2019); 

এটি কাজ করে, কারণ +ল্যাম্বডাকে একটি ফাংশন পয়েন্টারে রূপান্তরিত করবে এবং উভয় ফাংশন পয়েন্টারে একই ধরণের (মত কিছু void (*)(int)) রয়েছে।

জিসিসি এবং কলংয়ের সাথে (তবে এমএসভিসির সাথে নয়) +বাদ দেওয়া যেতে পারে, ল্যাম্বডাস এখনও ফাংশন পয়েন্টারে রূপান্তরিত হবে।


1
এটি যদিও ভিজ্যুয়াল স্টুডিওতে কাজ করবে না। তাদের এক্সটেনশন যা কোনও ল্যাম্বডাকে বিভিন্ন কলিং কনভেনশনে রূপান্তর করতে দেয় তা এড়াতে দেয়।
গিলিয়াম র্যাকিকোট

@ গুইলাউম্যারাসিকোট, এই নোটের জন্য ধন্যবাদ। আপনি দয়া করে একটি লিঙ্ক দিতে পারেন যেখানে আমি এটি সম্পর্কে আরও পড়তে পারি?
এভগ


2
@ গুইলাউম্যারাসিকোট এটি সাম্প্রতিক এমএসভিসি সংস্করণে সংকলিত বলে মনে হচ্ছে। Godbolt.org/z/ZQLWxy
ব্রায়ান

@ ব্রায়ান ওহ! এটি দুর্দান্ত খবর। এখন আমাকে কিছু কোড পরিবর্তন করতে হবে। ধন্যবাদ!
গিলিয়াম র্যাকিকট

10

সংকলকটি কোন ধরণের autoহওয়া উচিত তা সিদ্ধান্ত নিতে পারে না :

auto lambda = condition ? lambda1 : lambda2;

যেহেতু প্রতিটি ল্যাম্বদা একটি আলাদা এবং অনন্য ধরণের রয়েছে।

কাজ করার একটি উপায় হ'ল:

auto lambda = [&](T& arg) {
     return (condition ? lambda1(arg) : lambda2(arg));
}

8

এটি সংকলন করে না কারণ প্রতিটি ল্যাম্বডায় একটি অনন্য প্রকার রয়েছে, এর জন্য কোনও সাধারণ ধরণের নেই ?:

আপনি এগুলিকে গুটিয়ে রাখতে পারেন std::function<void(T&)>, যেমন

auto lamba1 = [&](T& arg) {
  ...
};
auto lambda2 = [&](T& arg) {
  ...
};
auto lambda = condition ? std::function(lambda1) : lambda2; // C++17 class template deduction

8

2 lambdas (যেহেতু lambda1এবং lambda2) 2 বিভিন্ন ধরনের হয় ?:না অনুমান রিটার্ন টাইপ করতে পারেন lambdaথেকে lambda1এবং lambda2। এটি ঘটে কারণ এই 2 একে অপরের সাথে রূপান্তরিত হয় না।

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