সদস্য ফাংশনের অভ্যন্তরে লাম্বদা ক্যাপচার তালিকায় সদস্য ভেরিয়েবল ব্যবহার করে


145

নিম্নলিখিত কোডটি জিসিসি 4.5.1 সহ কম্পাইল করে তবে ভিএস 2010 এসপি 1 এর সাথে নয়:

#include <iostream>
#include <vector>
#include <map>
#include <utility>
#include <set>
#include <algorithm>

using namespace std;
class puzzle
{
        vector<vector<int>> grid;
        map<int,set<int>> groups;
public:
        int member_function();
};

int puzzle::member_function()
{
        int i;
        for_each(groups.cbegin(),groups.cend(),[grid,&i](pair<int,set<int>> group){
                i++;
                cout<<i<<endl;
        });
}
int main()
{
        return 0;
}

এটি ত্রুটি:

error C3480: 'puzzle::grid': a lambda capture variable must be from an enclosing function scope
warning C4573: the usage of 'puzzle::grid' requires the compiler to capture 'this' but the current default capture mode does not allow it

সুতরাং,

1> কোন সংকলক সঠিক?

2> ভিএস 2010 এ আমি কীভাবে ল্যাম্বদার ভিতরে সদস্য ভেরিয়েবলগুলি ব্যবহার করতে পারি?


1
দ্রষ্টব্য: এটি হওয়া উচিত pair<const int, set<int> >, এটি কোনও মানচিত্রের আসল জুটি ধরণের। এটি সম্ভবত একটি রেফারেন্স-টু-কনস্টেরও হওয়া উচিত।
Xeo

সম্পর্কিত; খুব সহায়ক: thispointer.com/…
গ্যাব্রিয়েল স্ট্যাপলস

উত্তর:


157

আমি বিশ্বাস করি এই মুহুর্তে ভিএস ২০১০ ঠিক আছে, এবং আমি পরীক্ষা করে দেখি যে আমার কাছে স্ট্যান্ডার্ড সুবিধা আছে কিনা, তবে বর্তমানে আমি তা করি না।

এখন, এটি ঠিক ত্রুটি বার্তার মতো বলে: আপনি ল্যাম্বদার ঘেরের বাইরে কোনও জিনিস ক্যাপচার করতে পারবেন না। The grid সংলগ্ন সুযোগে নয়, তবে thisএটি ( সদস্যের কার্যক্রমে প্রতিটি অ্যাক্সেস gridপ্রকৃতপক্ষে ঘটে this->grid)। আপনার ব্যবহারের জন্য, ক্যাপচারিংয়ের thisকাজ, যেহেতু আপনি এখনই এটি ব্যবহার করবেন এবং আপনি এটি অনুলিপি করতে চান নাgrid

auto lambda = [this](){ std::cout << grid[0][0] << "\n"; }

তবে, আপনি যদি গ্রিডটি সঞ্চয় করতে চান এবং এটির পরে অ্যাক্সেসের জন্য অনুলিপি করতে চান, যেখানে আপনার puzzleবস্তু ইতিমধ্যে ধ্বংস হয়ে যেতে পারে, আপনাকে একটি অন্তর্বর্তী, স্থানীয় অনুলিপি তৈরি করতে হবে:

vector<vector<int> > tmp(grid);
auto lambda = [tmp](){}; // capture the local copy per copy

† আমি সরলকরণ করছি - "স্কোপ পৌঁছানোর জন্য" গুগল বা সমস্ত ভৌতিক বিবরণের জন্য §5.1.2 দেখুন।


1
এটি আমার কাছে বেশ সীমাবদ্ধ বলে মনে হচ্ছে। কোনও সংকলককে কেন এমন জিনিস আটকাতে হবে তা আমি বুঝতে পারি না। এটি বাইন্ডের সাথে ভালভাবে কাজ করে, যদিও সিনট্যাক্সটি অস্ট্রিম বাম শিফট অপারেটরের সাথে ভয়ঙ্কর।
জিন-সাইমন ব্রোচু

3
গেল tmpএকটি হতে const &করার gridঅনুলিপি উপর কমান? আমরা এখনও কমপক্ষে একটি অনুলিপি, লাম্বডায় অনুলিপি ( [tmp]) চাই, তবে দ্বিতীয় অনুলির প্রয়োজন নেই।
অ্যারন ম্যাকডেইড

4
সমাধানটি অপ্রয়োজনীয় অতিরিক্ত অনুলিপি তৈরি করতে পারে gridযদিও এটি সম্ভবত অনুকূলিত হয়ে যায়। সংক্ষিপ্ত এবং আরও ভাল: auto& tmp = grid;ইত্যাদি
টম সায়ার্লি

4
আপনার যদি সি ++ 14 উপলব্ধ থাকে তবে আপনি [grid = grid](){ std::cout << grid[0][0] << "\n"; }অতিরিক্ত অনুলিপি এড়াতে পারেন
সিগি

এটি error: capture of non-variable ‘puzzle::grid’
জিসিসি

108

বিকল্পগুলির সংক্ষিপ্তসার:

ক্যাপচার this:

auto lambda = [this](){};

সদস্যকে স্থানীয় রেফারেন্স ব্যবহার করুন:

auto& tmp = grid;
auto lambda = [ tmp](){}; // capture grid by (a single) copy
auto lambda = [&tmp](){}; // capture grid by ref

সি ++ 14:

auto lambda = [ grid = grid](){}; // capture grid by copy
auto lambda = [&grid = grid](){}; // capture grid by ref

উদাহরণ: https://godbolt.org/g/dEKVGD


5
ইন্টারেস্টাইজার সিনট্যাক্স সহ ক্যাপচারের কেবল সুস্পষ্ট ব্যবহারই এই কাজটি আকর্ষণীয় (যেমন সি ++ 14 এ [&grid]এখনও কাজ করা কার্যকর হয় না) ing এটি জানতে পেরে খুব আনন্দিত!
ohruunuruus

1
ভাল সংক্ষিপ্তসার। আমি সি ++ ১৪ সিনট্যাক্সটি খুব সুবিধাজনক হিসাবে
পেয়েছি

22

আমি বিশ্বাস করি, আপনি ক্যাপচার প্রয়োজন this


1
এটি সঠিক, এটি এই পয়েন্টারটি ক্যাপচার করবে এবং আপনি এখনও gridসরাসরি সরাসরি উল্লেখ করতে পারেন । সমস্যা হচ্ছে, গ্রিডটি কপি করতে চাইলে কী হবে? এটি আপনাকে এটি করতে দেয় না।
Xeo

9
আপনি পারেন, তবে কেবল চক্রাকারে: আপনাকে একটি স্থানীয় অনুলিপি তৈরি করতে হবে এবং ল্যাম্বডায় এটি ক্যাপচার করতে হবে । ল্যাম্বডাসের সাথে এটিই নিয়ম, আপনি ঘেরের সুযোগের বাইরে কড়া ক্যাপচার করতে পারবেন না।
Xeo

অবশ্যই আপনি কপি করতে পারেন। আমি বলতে চাইছিলাম আপনি অবশ্যই এটি কপি-ক্যাপচার করতে পারবেন না।
মাইকেল ক্রেলিন - হ্যাকার

আমি যা বর্ণনা করেছি তা অনুলিপি স্থানীয় কপির মাধ্যমে একটি অনুলিপি ক্যাপচার করে - আমার উত্তরটি দেখুন। এটি বাদ দিয়ে, আমি সদস্য ভেরিয়েবল ক্যাপচারের কোনও উপায় জানি না।
Xeo

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

14

একটি বিকল্প পদ্ধতি যা ল্যাম্বডাকে পুরোপুরি অ্যাক্সেস দেওয়ার চেয়ে সীমাবদ্ধ করে দেয় তা thisহল সদস্য ভেরিয়েবলের স্থানীয় রেফারেন্সে পাস করা, যেমন

auto& localGrid = grid;
int i;
for_each(groups.cbegin(),groups.cend(),[localGrid,&i](pair<int,set<int>> group){
            i++;
            cout<<i<<endl;
   });

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