আমি কেন সি ++ 11 এ ল্যাম্বডাস (একই ধরণের) ভেক্টর তৈরি করতে পারি না?


90

আমি ল্যাম্বদার একটি ভেক্টর তৈরি করার চেষ্টা করছিলাম, কিন্তু ব্যর্থ হয়েছিল:

auto ignore = [&]() { return 10; };  //1
std::vector<decltype(ignore)> v;     //2
v.push_back([&]() { return 100; });  //3

# 2 লাইন অবধি , এটি সূক্ষ্ম সংকলন করে । তবে # 3 লাইনটি সংকলন ত্রুটি দেয় :

ত্রুটি: 'স্টাড :: ভেক্টর <প্রধান () :: <লাম্বদা () >> :: পুশ_ব্যাক (প্রধান () :: <লাম্বদা ()>)' তে কল করার জন্য কোনও মেলানো ফাংশন নেই

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


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

উত্তর:


137

প্রতিটি ল্যাম্বডায় আলাদা ধরণের থাকে ven এমনকি যদি তাদের একই স্বাক্ষর থাকে। আপনাকে অবশ্যই রান-টাইম এনক্যাপসুলেটিং কনটেইনার ব্যবহার করতে হবে যেমন std::functionআপনি যদি এর মতো কিছু করতে চান।

যেমন:

std::vector<std::function<int()>> functors;
functors.push_back([&] { return 100; });
functors.push_back([&] { return  10; });

52
একশো লোকের বিকাশকারী দল পরিচালনা করা আমার কাছে দুঃস্বপ্নের মতো শোনাচ্ছে :)
জেরেমি ফ্রাইজনার

10
এছাড়াও, ভুলে যাবেন না যে ক্যাপচারহীন ল্যাম্বডাস ([]-স্টাইল) ফাংশন পয়েন্টারগুলিতে অবনতি করতে পারে। সুতরাং তিনি একই ধরণের ফাংশন পয়েন্টারগুলির একটি অ্যারে সঞ্চয় করতে পারেন। মনে রাখবেন যে ভিসি 10 এখনও এটি বাস্তবায়ন করে না।
নিকল বোলাস

যাইহোক, এই উদাহরণগুলিতে যাইহোক ক্যাপচার-কম ব্যবহার করা উচিত নয়? নাকি দরকার? - যাইহোক, ক্যাপচারলেস ল্যাম্বডা থেকে ফাংশন পয়েন্টারটি ভিসি 11 এ সমর্থিত বলে মনে হচ্ছে। যদিও এটি পরীক্ষা করে নি।
ক্লাইম

4
বিভিন্ন ধরণের ভেক্টর সংরক্ষণের ফাংশন তৈরি করা কি সম্ভব? অর্থ্যাৎ এটিকে সীমাবদ্ধ করার পরিবর্তে std::function<int(), আমি কি বিভিন্ন ফাংশন প্রোটোটাইপগুলি ব্যবহার করতে পারি?
manatttta

4
@ মানাত্ত্তা কী বলবেন? একই ধরণের অবজেক্টগুলি সংরক্ষণ করার জন্য, তাদের একত্রে সংগঠিত ও ম্যানিপুলেট করার জন্য ধারকগুলি বিদ্যমান। আপনি পাশাপাশি জিজ্ঞাসা করতে পারেন 'আমি এবং vectorউভয়ই সঞ্চয় করতে পারি ?' এবং উত্তরটি একই: না, কারণ এটি উদ্দেশ্যযুক্ত ব্যবহার নয়। কোনও কনটেইনারটিতে পৃথক জিনিস রাখার জন্য পর্যাপ্ত ধরনের মুছে ফেলার জন্য আপনি 'বৈকল্পিক' শৈলীর ক্লাস ব্যবহার করতে পারেন, যখন কোনও ব্যবহারকারীর জন্য 'আসল' টাইপ নির্ধারণ করার পদ্ধতিও অন্তর্ভুক্ত ছিল এবং সুতরাং কী করতে হবে তা বেছে নিন (যেমন কীভাবে কল করবেন) প্রতিটি উপাদান ... কিন্তু আবার, কেন এত দৈর্ঘ্য হয়? কোন বাস্তব যুক্তি আছে? std::functionstd::string
আন্ডারস্কোর_২

41

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

এর একটি সমাধান এর std::function<int()>পরিবর্তে ভেক্টর তৈরি করা।

auto ignore = [&]() { return 10; };
std::vector<std::function<int()>> v;
v.push_back(ignore);
v.push_back([&]() { return 100; });

অন্য নোটে, [&]আপনি যখন কোনও কিছু ক্যাপচার করছেন না তখন এটি ব্যবহার করা ভাল ধারণা নয়।


14
প্রয়োজন না ()lambdas যে কোন যুক্তি নেওয়া জন্য।
কুকুরছানা

18

অন্যরা যা বলেছে তা প্রাসঙ্গিক হলেও ল্যাম্বদার একটি ভেক্টর ঘোষণা এবং ব্যবহার এখনও সম্ভব, যদিও এটি খুব কার্যকর নয়:

auto lambda = [] { return 10; };
std::vector<decltype(lambda)> vec;
vec.push_back(lambda);

সুতরাং, আপনি সেখানে কোনও লম্বা লম্বা স্টোর রাখতে পারেন, যতক্ষণ না এটি অনুলিপি / চালানো যায় lambda!


যা আসলে কার্যকর হতে পারে যদি পুশব্যাকটি বিভিন্ন পরামিতিগুলির সাথে একটি লুপে ঘটে। সম্ভবত অলস মূল্যায়নের উদ্দেশ্যে।
মহুজা

7
না আপনি ভেক্টরে প্যারামিটারগুলি রাখবেন না, কেবলমাত্র ফাংশন অবজেক্ট .. সুতরাং এটি একই ল্যাম্বডারের সমস্ত অনুলিপি সহ ভেক্টর হবে
hariseldon78

16

যদি আপনার ল্যাম্বদা স্টেটলেস হয়, অর্থাত্, [](...){...}সি ++ 11 এটিকে কোনও ফাংশন পয়েন্টারে পরিণত করতে দেয়। তত্ত্ব অনুসারে, একটি সি ++ 11 কমপ্লায়েন্ট সংকলক এটি সংকলন করতে সক্ষম হবে:

auto ignore = []() { return 10; };  //1 note misssing & in []!
std::vector<int (*)()> v;     //2
v.push_back([]() { return 100; });  //3

4
রেকর্ড auto ignore = *[] { return 10; };জন্য ignoreএকটি করতে হবে int(*)()
লুক ড্যান্টন

4
@ লু, ওহ স্থূল! তারা কখন এটি যুক্ত করেছিল?
এমএসএএন

4
ঠিক আছে, যেহেতু রূপান্তর ফাংশন যা প্রথম স্থানে কোনও ফাংশন পয়েন্টার নিতে দেয় তা হ'ল আদেশ করা হয় না explicit, তাই ল্যাম্বডা এক্সপ্রেশনটিকে অবজ্ঞা করা বৈধ এবং রূপান্তরটির ফলে পয়েন্টারটিকে অবজ্ঞা করে। তারপরে autoক্ষয়গুলি ব্যবহার করে সেই রেফারেন্সটিকে পয়েন্টার হিসাবে ফিরে। (ব্যবহার করে auto&বা auto&&রেফারেন্সটি রেখেছিল।)
লুস ড্যান্টন

আহ ... ফলাফল পয়েন্টার অবচয়। এটা বোধগম্য. নিখোঁজ ছিল ()ইচ্ছাকৃত নাকি দুর্ঘটনাক্রমে?
এমএসএন

ইচ্ছাকৃত, ল্যাম্বডা এক্সপ্রেশন সমতুল্য (তবে দুটি অক্ষর ছোট)।
ড্যান্টন

6

আপনি একটি ল্যাম্বদা উত্পন্ন ফাংশন ব্যবহার করতে পারেন (নওয়াজের প্রস্তাবিত ফিক্সের সাথে আপডেট হয়েছে):

#include <vector>
#include <iostream>

int main() {
    auto lambda_gen = [] (int i) {return [i](int x){ return i*x;};} ;

    using my_lambda = decltype(lambda_gen(1));

    std::vector<my_lambda> vec;

    for(int i = 0; i < 10; i++) vec.push_back(lambda_gen(i));

    int i = 0;

    for (auto& lambda : vec){
        std::cout << lambda(i) << std::endl;
        i++;
    }
}

তবে আমি মনে করি আপনি মূলত এই সময়ে আপনার নিজের ক্লাস তৈরি করেছেন made অন্যথায় যদি ল্যাম্বডাসের সম্পূর্ণ আলাদা ক্যাপুট্রেস / আরগস থাকে তবে আপনার সম্ভবত একটি টিপল ব্যবহার করতে হবে।


এটি একটি ফাংশন এ মোড়ানো ভাল ধারণা lambda_genযা একটি lambda নিজেই হতে পারে। যাইহোক, auto a = lambda_gen(1);একটি অপ্রয়োজনীয় কল করে, যা আমরা এটি লিখলে এড়ানো যায় decltype(lambda_gen(1))
নওয়াজ

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

না। অভ্যন্তরের decltype যে কোনও কিছুই মূল্যহীন নয় , তাই কলটি আসলে করা হয়নি। এটি একই ক্ষেত্রে একই অবস্থা sizeof। এছাড়াও, এই কোডটি সি ++ 11 এ কাজ করবে না আপনি এমনকি ট্রেলিং রিটার্ন টাইপ যুক্ত করলেও !!
নওয়াজ

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