ল্যাম্বডা ফাংশন শিখিয়ে দেওয়া যায়?


230

সি ++ 11 এ ল্যাম্বডা ফাংশনটি টেম্পলেট করার কোনও উপায় আছে কি? বা এটি উদ্ভাসিত হওয়া সহজাতভাবে খুব নির্দিষ্ট?

আমি বুঝতে পারি যে পরিবর্তে আমি একটি ক্লাসিক টেম্প্লেটেড ক্লাস / ফান্টেক্টর সংজ্ঞায়িত করতে পারি, তবে প্রশ্নটি আরও বেশি: ভাষাটি ল্যাম্বডা ফ্যাম্পলিংয়ের অনুমতি দেয় কি?


এমন কোনও ব্যবহারের কেস রয়েছে যেখানে ল্যাম্বডা টেম্পলেটটি কার্যকর হবে?
জেমস ম্যাকনেলিস

7
জেমস: আপনি একটি ফাংশন পুনরুক্তি করতে একটি ফাংশন তৈরি করতে পারে (প্রয়োজনীয় দরকারী নয়)।
জো ডি

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

উত্তর:


181

আপডেট 2018: সি ++ 20 টি টেম্প্লেটেড এবং কনসেপ্টুয়ালাইজড ল্যাম্বডাসের সাথে আসবে। বৈশিষ্ট্যটি ইতিমধ্যে মানক খসড়াটিতে সংহত করা হয়েছে।


আপডেট 2014: সি ++ 14 এই বছর প্রকাশিত হয়েছে এবং এখন পলিমর্ফিক ল্যাম্বডাসকে এই উদাহরণের মতো একই সিনট্যাক্স সহ সরবরাহ করে। কিছু বড় সংকলক ইতিমধ্যে এটি প্রয়োগ করে।


এটি দাঁড়িয়ে (সি ++ 11 এ), দুঃখজনকভাবে না। বহুমুখী ল্যাম্বডাস নমনীয়তা এবং শক্তির দিক থেকে দুর্দান্ত।

তারা মনোমরফিক হয়ে ওঠার মূল কারণটি ছিল ধারণার কারণ। ধারণাগুলি এই কোড পরিস্থিতিটিকে কঠিন করে তুলেছে:

template <Constraint T>
void foo(T x)
{
    auto bar = [](auto x){}; // imaginary syntax
}

একটি সীমাবদ্ধ টেম্পলেটে আপনি কেবল অন্যান্য সীমাবদ্ধ টেম্পলেট কল করতে পারেন। (অন্যথায় সীমাবদ্ধতাগুলি পরীক্ষা করা যায়নি)) fooপ্রার্থনা করতে পারেন bar(x)? ল্যাম্বডায় কোন বাধা রয়েছে (এর প্যারামিটারটি কেবলমাত্র একটি টেম্পলেট, সর্বোপরি)?

ধারণাগুলি এই ধরণের জিনিস মোকাবেলার জন্য প্রস্তুত ছিল না; এর জন্য আরও স্টাফের প্রয়োজন হবে late_check(যেখানে ধারণাটি চাওয়ার আগে পরীক্ষা করা হয়নি) এবং স্টাফ। সিম্পলারের মধ্যে কেবল এটি সব ফেলে দেওয়া এবং মনোমর্ফিক ল্যাম্বডাসের সাথে লেগে থাকা ছিল।

যাইহোক, সি ++ 0 এক্স থেকে ধারণাগুলি অপসারণের সাথে বহুবর্ষীয় ল্যাম্বডাস আবার একটি সহজ প্রস্তাব হয়ে যায়। তবে আমি এর জন্য কোনও প্রস্তাব পাই না। :(


5
সহজ ... ধারণাগুলি পুনরায় প্রবর্তন এবং এমন বৈশিষ্ট্যগুলি এড়িয়ে চলা যাতে এগুলি জটিল করে তোলে সেগুলি বাদ দেওয়া।

6
আমার ধারণা আমি ধারণার চেয়ে পলিমারফিক ল্যাম্বডাস চাইতাম। উদাহরণটি কীভাবে কিছু অনুপ্রাণিত করে তা আমি বুঝতে পারি না; আপনি এটিকে কেবল একটি ত্রুটি হিসাবে নিষেধ করতে পারেন, এবং ল্যাম্বডাকে মনোমর্ফিক [] (টি এক্স) {} বা একটি সীমাবদ্ধ টেম্পলেট [] টেমপ্লেট <কনস্ট্রেন্ট টি> (টি এক্স) {be করতে হবে, যা মিলার জন্য স্থিতি যাচাই করা যেতে পারে। এটি সম্ভব না হওয়ার কোনও কারণ আছে?
ড্রিপজা

13
আপনাকে ধারণাগুলি এবং বহুমুখী ল্যাম্বডাসের
ডেভ আব্রাহাম

3
পলিমারফিক ল্যাম্বডাসের প্রস্তাব এখানে রয়েছে: ওপেন-std.org/jtc1/sc22/wg21/docs/papers/2012/n3418.pdf এবং খেলনা বাস্তবায়নের ঝাঁকুনিতে
রাদিফ শরাফুলিন

18
বহুরুপী Lambdas সি ++ 14 হবে, অন্তত তারা এখন দ্বারা কমিউনিটি ড্রাফ্টে আছেন :)
আর্নি Mertz

37

অন্যান্য উত্তরগুলিতে বর্ণিত হিসাবে সি ++ ১১ টি decltype()ল্যাম্বডাস টেম্পলেট করা যায় না তবে একটি টেম্প্লেটেড ক্লাস বা ফাংশনের মধ্যে ল্যাম্বডা ব্যবহার করার সময় মনে হয় এটি সাহায্য করবে।

#include <iostream>
#include <string>

using namespace std;

template<typename T>
void boring_template_fn(T t){
    auto identity = [](decltype(t) t){ return t;};
    std::cout << identity(t) << std::endl;
}

int main(int argc, char *argv[]) {
    std::string s("My string");
    boring_template_fn(s);
    boring_template_fn(1024);
    boring_template_fn(true);
}

ছাপে:

My string
1024
1

আমি খুঁজে পেয়েছি যে টেম্প্লেটেড কোডের সাথে কাজ করার সময় এই কৌশলটি সাহায্য করে তবে বুঝতে পেরেছেন যে লাম্বডাস তাদের নিজেরাই শিখানো যায় না।


26
Tdecltype(t)এই উদাহরণের জায়গায় ভাল কাজ করবে ।
ব্যবহারকারী 2023370

26

সি ++ ১১-এ, ল্যাম্বদা ফাংশনগুলি টেম্প্লেটেড করা যায় না, তবে আইএসও সি ++ স্ট্যান্ডার্ডের পরবর্তী সংস্করণে (প্রায়শই সি ++ 14 বলা হয়) এই বৈশিষ্ট্যটি চালু করা হবে। [উৎস]

ব্যবহারের উদাহরণ:

auto get_container_size = [] (auto container) { return container.size(); };

দ্রষ্টব্য যে সিন্ট্যাক্সটি কীওয়ার্ডটি ব্যবহার করে auto, প্রকারের ছাড়ের প্রকারটি ছাড়ার প্রকারগুলি ব্যবহার করবে না auto, পরিবর্তে টেমপ্লেট আর্গুমেন্ট ছাড়ের নিয়ম ব্যবহার করবে। জেনেরিক ল্যাম্বডা এক্সপ্রেশনগুলির প্রস্তাবও দেখুন (এবং এটির আপডেট )।


5
autoটাইপ ছাড়ের নিয়মগুলি বিশেষত templateফাংশন আর্গুমেন্ট ছাড়ের মতো হিসাবে সংজ্ঞায়িত করা হয় ।
আন্ডারস্কোর_

10

আমি সচেতন যে এই প্রশ্নটি C ++ 11 সম্পর্কে। তবে, যারা এই পৃষ্ঠায় গুগল করেছেন এবং অবতরণ করেছেন তাদের জন্য, টেম্প্লেটেড ল্যাম্বডাস এখন সি ++ 14 এ সমর্থিত এবং জেনেরিক ল্যাম্বডাস নামে চলে।

[তথ্য] বেশিরভাগ জনপ্রিয় সংকলক এখন এই বৈশিষ্ট্যটিকে সমর্থন করে। মাইক্রোসফ্ট ভিজ্যুয়াল স্টুডিও 2015 সমর্থন করে। ঝাঁকুনি সমর্থন করে। জিসিসি সমর্থন করে।


6

আমি এই সম্পর্কে কি অবাক:

template <class something>
inline std::function<void()> templateLamda() {
  return [](){ std::cout << something.memberfunc() };
}

আমি এই জাতীয় অনুরূপ কোড ব্যবহার করেছি, একটি টেমপ্লেট উত্পন্ন করতে এবং আশ্চর্য হওয়ার জন্য যে সংকলকটি "মোড়ানো" ফাংশনটি অপ্টিমাইজ করবে।


2
কি সংকলন? করেছি?
নিকো বেরোগুরি

4

পলিমারফিক ল্যাম্বডাসের জন্য বুস্ট.ফোনিক্সটি দেখুন: http://www.boost.org/doc/libs/1_44_0/libs/spirit/phoenix/doc/html/index.html এর দ্বারা সি ++ 0x প্রয়োজন হয় না উপায় :)


2
আমি এটি সম্পর্কে ইতিমধ্যে জানি তবে প্রশ্নটি ঠিক যাইহোক নতুন মান সম্পর্কে;)
ক্লাইম

ঠিক আছে :) সি ++ 0 এক্স ল্যাম্বডাস একচেটিয়া এবং দুর্ভাগ্যক্রমে টেম্পলেট করা যায় না।
usta

3

এখানে একটি জিসিসি এক্সটেনশন রয়েছে যা ল্যাম্বদা টেমপ্লেটগুলিকে মঞ্জুরি দেয় :

// create the widgets and set the label
base::for_each(_widgets, [] <typename Key_T, typename Widget_T>
                         (boost::fusion::pair<Key_T, Widget_T*>& pair) -> void {
                             pair.second = new Widget_T();
                             pair.second->set_label_str(Key_T::label);
                          }
              );

যেখানে _widgetsএকটিstd::tuple< fusion::pair<Key_T, Widget_T>... >


FWIW, এটি সি ++ 20 এ স্ট্যান্ডার্ড সিনট্যাক্সে পরিণত হয়েছে।
এলএফ

2

আমি পতাকাটির version 5.0.1সাথে সংকলনকারী সর্বশেষতম ঝনঝনির সাথে খেলছি -std=c++17এবং ল্যাম্বডাসের জন্য অটো টাইপ পরামিতিগুলির জন্য এখন কিছু সুন্দর সমর্থন রয়েছে:

#include <iostream>
#include <vector>
#include <stdexcept>

int main() {
    auto slice = [](auto input, int beg, int end) {
        using T = decltype(input);
        const auto size = input.size();
        if (beg > size || end > size || beg < 0 || end < 0) {
            throw std::out_of_range("beg/end must be between [0, input.size())");
        }
        if (beg > end) {
            throw std::invalid_argument("beg must be less than end");
        }
        return T(input.begin() + beg, input.begin() + end);
    };
    auto v = std::vector<int> { 1,2,3,4,5 };
    for (auto e : slice(v, 1, 4)) {
        std::cout << e << " ";
    }
    std::cout << std::endl;
}

1

এখানে একটি সমাধান যা কাঠামোর মধ্যে লাম্বা জড়িত জড়িত:

template <typename T>                                                   
struct LamT                                                             
{                                                                       
   static void Go()                                                     
   {                                                                    
      auto lam = []()                                                   
      {                                                                 
         T var;                                                         
         std::cout << "lam, type = " << typeid(var).name() << std::endl;
      };                                                                

      lam();                                                            
   }                                                                    
};   

ব্যবহার করতে:

LamT<int>::Go();  
LamT<char>::Go(); 
#This prints 
lam, type = i
lam, type = c

এটির সাথে প্রধান সমস্যা (অতিরিক্ত টাইপিংয়ের পাশাপাশি) আপনি অন্য কাঠামোর মধ্যে এই কাঠামোর সংজ্ঞা এম্বেড করতে পারবেন না বা পাবেন (জিসিসি 4.9)

error: a template declaration cannot appear at block scope

আমি এটি করার চেষ্টাও করেছি:

template <typename T> using LamdaT = decltype(                          
   [](void)                                                          
   {                                                                 
       std::cout << "LambT type = " << typeid(T).name() << std::endl;  
   });

আশা করি যে আমি এটি এর মতো ব্যবহার করতে পারি:

LamdaT<int>();      
LamdaT<char>();

তবে আমি সংকলক ত্রুটি পেয়েছি:

error: lambda-expression in unevaluated context

সুতরাং এটি কাজ করে না ... তবে এটি সংকলন করলেও এটি সীমিতভাবে ব্যবহারযোগ্য হবে কারণ আমাদের এখনও ফাইল স্কোপে "ল্যামডেট ব্যবহার" করতে হবে (কারণ এটি একটি টেমপ্লেট) যা ধরণের উদ্দেশ্যকে পরাস্ত করে? lambdas।


1

আমি নিশ্চিত না কেন অন্য কেউ এটির পরামর্শ দেয়নি তবে আপনি একটি টেম্প্লেটেড ফাংশন লিখতে পারেন যা ল্যাম্বদা ফাংশনগুলি ফিরিয়ে দেয়। নিম্নলিখিতগুলি আমার সমস্যার সমাধান করেছে, আমি এই পৃষ্ঠায় আসার কারণ:

template <typename DATUM>
std::function<double(DATUM)> makeUnweighted() {
  return [](DATUM datum){return 1.0;};
}

এখন যখনই আমি কোনও ফাংশন চাই যা প্রদত্ত ধরণের আর্গুমেন্ট গ্রহণ করে (যেমন std::string), আমি কেবল বলি

auto f = makeUnweighted<std::string>()

এবং এখন f("any string")ফিরে 1.0

এটি "টেম্প্লেটেড ল্যাম্বডা ফাংশন" দ্বারা আমি কী বোঝাতে চাইছি তার একটি উদাহরণ। (এই নির্দিষ্ট ক্ষেত্রেটি স্বয়ংক্রিয়ভাবে একটি জড় ওজনকরণ ক্রিয়াকলাপ সরবরাহ করতে ব্যবহৃত হয় যখন কেউ তাদের ডেটা যাই হোক না কেন তার ডেটা ওজন করতে চায় না))


2
ল্যাম্বডা তৈরির আগে আপনি ল্যাম্বডা যুক্তি যুক্তির ধরণটি জানেন তবে এটি কেবলমাত্র কাজ করে, সেক্ষেত্রে আপনি কেবল নির্দিষ্ট ধরণের যুক্তি হিসাবে ল্যাম্বডা ব্যবহার করতে পারেন। পলিমারফিক ল্যাম্বডা এর বিন্দুটি হল একটি আর্গুমেন্ট ধরণের কাজটি করা কাজটি আপনি যখন কোডের কোডটি লেখেন কখনই জানেন না। মূলত, এটি সম্পূর্ণ আলাদা, যে কারণে এটি প্রস্তাব দেওয়া হয়নি।
ক্লাইম

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