একটি "স্প্যান" কী এবং আমি কখন এটি ব্যবহার করব?


236

সাম্প্রতিককালে আমি আমার কোডটিতে ব্যবহার করার জন্য পরামর্শ span<T>পেয়েছি, বা এখানে এমন কিছু উত্তর দেখেছি যা এখানে ব্যবহার করা হয় span- সম্ভবত কোনও ধরণের ধারক ব্যবহার করে। তবে - আমি সি ++ 17 স্ট্যান্ডার্ড লাইব্রেরিতে এর মতো কিছুই পাই না।

সুতরাং এই রহস্যময়টি কী span<T>এবং কেন (বা কখন) এটি মানসম্মত না হলে এটি ব্যবহার করা ভাল ধারণা?


std::spanএটি 2017 সালে প্রস্তাবিত হয়েছিল It এটি C ++ 17 বা C ++ 20 এর ক্ষেত্রে প্রযোজ্য। এছাড়াও P0122R5 দেখুন, স্প্যান: অবজেক্টের সিকোয়েন্সের জন্য সীমানা-সুরক্ষিত দর্শনগুলি । আপনি কি সত্যিই সেই ভাষাটিকে লক্ষ্য করতে চান? কম্পাইলাররা ধরার কয়েক বছর আগে এটি ঘটবে।
jww

6
@jww: বিঘত এর সি ++ 11 বেশ ব্যবহারযোগ্য ... হিসাবে gsl::spanবদলে std::span। নীচে আমার উত্তর দেখুন।
einpoklum 24'18

সিপ্রেফারেন্স.কম এও নথিভুক্ত করা হয়েছে: en.cppreferences.com/w/cpp/container/span
কিথ থম্পসন

1
@ কিথথম্পসন: ২০১ in সালে তা ছিল না ...
ইিনপোকলুম

@jww সমস্ত সংকলক std :: span <> এখন সি ++ ২০ মোডে সমর্থন করে। এবং স্প্যান অনেকগুলি তৃতীয় পক্ষের লিব থেকে পাওয়া যায়। আপনি ঠিক বলেছেন - বছরগুলি ছিল: সুনির্দিষ্ট হতে 2 বছর।
কনটাঙ্গো

উত্তর:


272

এটা কি?

span<T>:

  • Tস্মৃতিতে কোথাও ধরণের মানগুলির সংলগ্ন ধারাটির খুব হালকা বিমূর্ততা ।
  • মূলত struct { T * ptr; std::size_t length; }একগুচ্ছ সুবিধাপ্রাপ্ত পদ্ধতি।
  • একটি মালিকানাবিহীন প্রকার (যেমন "মানের ধরণের" পরিবর্তে " একটি " রেফারেন্স- ধরণের "): এটি কখনই কোনও কিছু বরাদ্দ দেয় না বা হ্রাস করে না এবং স্মার্ট পয়েন্টারগুলিকে বাঁচিয়ে রাখে না।

এটি পূর্বে একটি হিসাবে array_viewএবং এমনকি আগে হিসাবে পরিচিত ছিল array_ref

আমি কখন এটি ব্যবহার করব?

প্রথমত, যখন না এটা ব্যবহার করার জন্য:

  • কোডে এটা ব্যবহার করবেন না যে শুধু শুরু ও শেষ iterators, কোন যুগল গ্রহণ করতে পারে মত std::sort, std::find_if, std::copyএবং যারা সুপার-জেনেরিক টেমপ্লেট করা ফাংশন সব।
  • আপনি যদি জানেন যে কোনও স্ট্যান্ডার্ড লাইব্রেরি ধারক (বা বুস্ট ধারক ইত্যাদি) থাকে তবে এটি ব্যবহার করবেন না যা আপনার কোডের জন্য উপযুক্ত। এটি তাদের কোনওটি সরবরাহ করার উদ্দেশ্যে নয়।

এখন কখন এটি ব্যবহার করবেন:

আপনার span<T>যথাক্রমে span<const T>মুক্ত স্থায়ী T*(যথাক্রমে ) পরিবর্তে (যথাক্রমে const T*) ব্যবহার করুন। সুতরাং, ফাংশনগুলি প্রতিস্থাপন করুন:

  void read_into(int* buffer, size_t buffer_size);

সঙ্গে:

  void read_into(span<int> buffer);

আমি কেন এটি ব্যবহার করব? কেন এটি একটি ভাল জিনিস?

ওহ, স্প্যানস দুর্দান্ত! একটি ব্যবহার করে span...

  • তার মানে আপনি যে পয়েন্টারটি + দৈর্ঘ্য / শুরু + শেষ পয়েন্টার সংমিশ্রণটি দিয়ে পছন্দ করেন ঠিক তেমন কোনও অভিনব, পিম্পড আউট স্ট্যান্ডার্ড লাইব্রেরি পাত্রে যেমন:

    • for (auto& x : my_span) { /* do stuff */ }
    • std::find_if(my_span.begin(), my_span.end(), some_predicate);

    ... তবে ওভারহেডের বেশিরভাগ ক্ষেত্রেই বেশিরভাগ ধারক শ্রেণীর ব্যয় হয় না।

  • সংকলকটি আপনাকে মাঝে মাঝে আরও কাজ করতে দেয়। উদাহরণস্বরূপ, এটি:

    int buffer[BUFFER_SIZE];
    read_into(buffer, BUFFER_SIZE);

    এটি হয়ে:

    int buffer[BUFFER_SIZE];
    read_into(buffer);

    ... যা আপনি যা করতে চান তা করবে। আরও দেখুন নির্দেশিকা পি .5

  • const vector<T>&যখন আপনি আপনার ডেটা মেমরির সাথে সংগতিপূর্ণ হওয়ার প্রত্যাশা করেন তখন ফাংশনে যাওয়ার উপযুক্ত যুক্তিযুক্ত বিকল্প । উচ্চ এবং শক্তিশালী সি ++ গুরু দ্বারা আর তিরস্কার করা হচ্ছে না!

  • স্থির বিশ্লেষণ সহজতর করে, তাই সংকলকটি আপনাকে বোকা বাগগুলি ধরতে সহায়তা করতে পারে।
  • রানটাইম বাউন্ডস-চেকিংয়ের জন্য ডিবাগ-সংকলন উপকরণের অনুমতি দেয় (অর্থাত্‍ spanপদ্ধতিগুলির মধ্যে কিছু বাউন্ড-চেকিং কোড থাকবে #ifndef NDEBUG... #endif)
  • নির্দেশ করে যে আপনার কোড (এটি স্প্যানটি ব্যবহার করছে) পয়েন্ট-টু মেমরির মালিক নয় doesn't

spanএস ব্যবহারের জন্য আরও বেশি অনুপ্রেরণা রয়েছে যা আপনি সি ++ মূল নির্দেশিকাতে খুঁজে পেতে পারেন - তবে আপনি প্রবাহটি ধরেন।

কেন এটি স্ট্যান্ডার্ড লাইব্রেরিতে নেই (সি ++ 17 হিসাবে)?

এটি স্ট্যান্ডার্ড লাইব্রেরিতে রয়েছে - তবে কেবল সি ++ ২০ হিসাবে। কারণে যে এটা এখনও বেশ তার বর্তমান ফর্ম, সাথে ভাবা নতুন হয় সি ++ কোর নির্দেশিকা প্রকল্প, যা শুধুমাত্র 2015. যেহেতু আকৃতি গ্রহণ করা হয়েছে (যদিও হিসাবে মন্তব্যকারী বাতলান, এটা আগের ইতিহাস রয়েছে।)

সুতরাং এটি স্ট্যান্ডার্ড লাইব্রেরিতে না থাকলে আমি কীভাবে এটি ব্যবহার করব?

এটি কোর গাইডলাইনসের সমর্থন লাইব্রেরির (জিএসএল) অংশ। বাস্তবায়নের:

  • মাইক্রোসফ্ট / নীল ম্যাকিনটোসের জিএসএলে একটি স্বতন্ত্র বাস্তবায়ন রয়েছে:gsl/span
  • জিএসএল-লাইট হ'ল পুরো জিএসএল (এটি এত বড় নয়, চিন্তা করবেন না) সহ একক শিরোনাম বাস্তবায়ন span<T>

জিএসএল বাস্তবায়ন সাধারণত একটি প্ল্যাটফর্ম ধরে নেয় যা C ++ 14 সমর্থন কার্যকর করে [ 14 ]। এই বিকল্প একক শিরোলেখ বাস্তবায়ন জিএসএল সুবিধার উপর নির্ভর করে না:

নোট করুন যে এই বিভিন্ন স্প্যান বাস্তবায়নের সাথে তারা কোন পদ্ধতি / সহায়তা কার্যক্রমে আসে তার কিছু পার্থক্য রয়েছে; এবং এগুলি স্ট্যান্ডার্ড লাইব্রেরিন সি ++ ২০ এ যাওয়া সংস্করণ থেকে কিছুটা পৃথক হতে পারে।


আরও পঠন: আপনি সি +++, P0122R7: স্প্যান: নীল ম্যাকিনটোস এবং স্টিফান জে লাভেভেজের অবজেক্টের সিকোয়েন্সের জন্য সীমাবদ্ধ-নিরাপদ মতামতের আগে চূড়ান্ত অফিশিয়াল প্রস্তাবনাতে সমস্ত বিবরণ এবং নকশা বিবেচনা খুঁজে পেতে পারেন । যদিও এটি কিছুটা দীর্ঘ। এছাড়াও, সি ++ ২০ এ স্প্যান তুলনা শব্দার্থবিজ্ঞানের পরিবর্তন ঘটে ( টনি ভ্যান ইয়ার্ডের এই সংক্ষিপ্ত কাগজ অনুসরণ করে)।


2
এটি একটি সাধারণ পরিসরকে (মানক পুনরুদ্ধারক + সেন্ডিনেল এবং পুনরুদ্ধারক + দৈর্ঘ্য, এমনকি পুনরাবৃত্তকারী + সেন্ডিনেল + দৈর্ঘ্যকে সমর্থন করে) এবং স্প্যানটিকে একটি সাধারণ টাইপডেফ তৈরি করতে আরও বুদ্ধিমান করে তোলে। কারণ, আপনি জানেন, এটি আরও সাধারণ।
Deduplicator

3
@ উত্সাহক: রেঞ্জগুলি সি ++ এ আসছে তবে বর্তমান প্রস্তাব (এরিক নিবলার দ্বারা) ধারণাগুলির জন্য সমর্থন প্রয়োজন। সুতরাং সি ++ 20 এর আগে নয়।
einpoklum

8
@ হিফিমলল: অ্যারেগুলি পয়েন্টারগুলিতে অবিলম্বে ক্ষয় হয় না। করার চেষ্টা করুন std::cout << sizeof(buffer) << '\n'এবং আপনি দেখতে পাবেন যে আপনি 100 মাপের (int) এর আকার পেয়েছেন।
einpoklum

4
@ জিম std::arrayএকটি ধারক, এটি মানগুলির মালিক। spanমালিকানাবিহীন
কালেথ

3
@ জিম: std::arrayসম্পূর্ণ ভিন্ন প্রাণী different এটির দৈর্ঘ্য সংকলন-সময়ে স্থির করা হয়েছে এবং ক্যালাথের ব্যাখ্যা অনুসারে এটি একটি রেফারেন্স-টাইপের পরিবর্তে মান-ধরণের।
einpoklum

1

@ আইনপোকলম এখানে তার উত্তরেspan যা আছে তা উপস্থাপনের জন্য বেশ ভাল কাজ করে । তবে, তার উত্তরটি পড়ার পরেও, নতুন কারওর পক্ষে এখনও স্ট্রিম-অফ-চিন্তার প্রশ্নগুলির ক্রম থাকা সহজ , যার পুরো উত্তর দেওয়া হয়নি, যেমন:

  1. spanসি অ্যারে থেকে আলাদা কীভাবে ? কেন শুধু তাদের একটি ব্যবহার করবেন না? দেখে মনে হচ্ছে এটি পরিচিত আকারগুলির মধ্যে কেবল একটি ...
  2. অপেক্ষা করুন, এটি একটি মত শোনাচ্ছে std::array, এর spanথেকে আলাদা কীভাবে ?
  3. ওহ, এটি আমাকে মনে করিয়ে দেয়, খুব একটা std::vectorভালো std::arrayলাগে না?
  4. আমি খুবই দ্বিধাগ্রস্ত. :( কি span?

সুতরাং, এখানে কিছু অতিরিক্ত স্পষ্টতা এখানে:

তাঁর উত্তরের প্রত্যক্ষ উক্তি - সাহসী আমার বিজ্ঞাপনগুলি সহ :

এটা কি?

span<T>:

  • Tস্মৃতিতে কোথাও ধরণের মানগুলির সংলগ্ন ধারাটির খুব হালকা বিমূর্ততা ।
  • মূলত একগুচ্ছ সুবিধা পদ্ধতি সহ একটি একক কাঠামো { T * ptr; std::size_t length; }(লক্ষ্য করুন এই থেকে সম্পূর্ণ ভিন্ন std::array<>কারণে spanপদ্ধতি অ্যাকসেসর সুবিধা, এর তুলনীয় সম্ভব std::arrayএকটি মাধ্যমে টাইপ করতে পয়েন্টারT এবং ধরনের দৈর্ঘ্য (উপাদানের সংখ্যা) T, যেহেতু std::arrayপ্রকৃত ধারক যা এক বা একাধিক ঝুলিতে মান ধরনের T।)
  • একটি মালিকানাবিহীন প্রকার (যেমন "মানের ধরণের" পরিবর্তে " একটি " রেফারেন্স- ধরণের "): এটি কখনই কোনও কিছু বরাদ্দ দেয় না বা হ্রাস করে না এবং স্মার্ট পয়েন্টারগুলিকে বাঁচিয়ে রাখে না।

এটি পূর্বে একটি হিসাবে array_viewএবং এমনকি আগে হিসাবে পরিচিত ছিল array_ref

এই সাহসী অংশগুলি কারও বোঝার জন্য সমালোচনা , সুতরাং সেগুলি মিস করবেন না বা তাদের ভুল পড়বেন না! একজন spanstructs এর একটি সি-অ্যারে নয়, না এটা ধরনের সি-অ্যারের একটি struct হয় Tপ্লাস অ্যারের দৈর্ঘ্য (এই মূলত কি হবে std::array ধারক হয়), না এটা পয়েন্টার structs এর একটি সি-অ্যারে Tদৈর্ঘ্য টাইপ করতে , বরং এটি টাইপ করার জন্য একটি একক পয়েন্টার সমেত একক কাঠামো , এবং দৈর্ঘ্য , যা সংক্ষিপ্ত মেমরি ব্লকের উপাদানগুলির (টাইপের ) সংখ্যা যা পয়েন্টারটি পয়েন্ট টাইপ করতে হয়! এইভাবে, আপনি ব্যবহার করে একমাত্র ওভারহেড যুক্ত করেছেনTTTspanপয়েন্টার এবং দৈর্ঘ্য সংরক্ষণ করার জন্য ভেরিয়েবলগুলি এবং আপনি যে কোনও সুবিধাযুক্ত অ্যাক্সেসর ফাংশন ব্যবহার করেন যা spanসরবরাহ করে।

এটি অপরিবর্তিত একটি std::array<>কারণ std::array<>প্রকৃতপক্ষে পুরো সংক্ষিপ্ত ব্লকের জন্য মেমরি বরাদ্দ করে, এবং এটি অপছন্দ std::vector<>কারণ কারণ std::vectorএটি মূলত কেবল একটি std::arrayযা গতিশীল বর্ধন (সাধারণত আকারে দ্বিগুণ) করে প্রতিবার এটি পূর্ণ হয় এবং আপনি এটিতে অন্য কিছু যুক্ত করার চেষ্টা করেন । এ std::arrayআকারে স্থির থাকে, এবং এটি একটি spanব্লকের স্মৃতি পরিচালনাও করে না যা এটি নির্দেশ করে, এটি কেবল মেমরির ব্লকের দিকে নির্দেশ করে, মেমরির ব্লকটি কত দীর্ঘ তা জানে, সি-অ্যারেতে ডেটা টাইপ কী তা জানে মেমরিতে, এবং সেই সংমিশ্রিত মেমরির উপাদানগুলির সাথে কাজ করতে সুবিধাজনক অ্যাক্সেসর ফাংশন সরবরাহ করে

এটা তোলে হয় সি অংশ ++ স্ট্যান্ডার্ডের:

std::spanসি ++ 20 হিসাবে সি ++ স্ট্যান্ডার্ডের অংশ। আপনি এখানে তার ডকুমেন্টেশন পড়তে পারেন: https://en.cppreferences.com/w/cpp/container/spanabsl::Span<T>(array, length)সি ++ 11 বা তার পরে আজ গুগল কীভাবে ব্যবহার করবেন তা দেখতে নীচে দেখুন।

সংক্ষিপ্ত বিবরণ এবং মূল তথ্যসমূহ:

  1. std::span<T, Extent>( Extent= "ক্রমানুসারে উপাদানের নম্বর, বা std::dynamic_extentগতিশীল যদি" কোনও স্প্যান মাত্র। পয়েন্ট মেমরি এবং অ্যাক্সেস করতে এটি সহজ করে তোলে, কিন্তু এটা পরিচালনা করে না!):
    1. https://en.cppreference.com/w/cpp/container/span
  2. std::array<T, N>(লক্ষ্য করুন এটির একটি নির্দিষ্ট আকার রয়েছে N!):
    1. https://en.cppreference.com/w/cpp/container/array
    2. http://www.cplusplus.com/reference/array/array/
  3. std::vector<T> (প্রয়োজনীয় হিসাবে স্বয়ংক্রিয়ভাবে আকারে আকারে বৃদ্ধি পায়):
    1. https://en.cppreference.com/w/cpp/container/vector
    2. http://www.cplusplus.com/reference/vector/vector/

আমি আজspan সি ++ 11 বা তার পরে কীভাবে ব্যবহার করতে পারি ?

গুগল তাদের "Abseil" লাইব্রেরি আকারে তাদের অভ্যন্তরীণ সি ++ 11 গ্রন্থাগার খোলা সন্ধান করেছে। এই লাইব্রেরিটি সি ++ 14 থেকে সি ++ 20 এবং সি ++ 11 এবং তার পরে কাজ করে এমন বৈশিষ্ট্যগুলি ছাড়িয়ে সরবরাহ করার উদ্দেশ্যে যাতে আপনি আজকের কালকের বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন। তারা বলে:

সি ++ স্ট্যান্ডার্ডের সাথে সামঞ্জস্যতা

গুগল অনেকগুলি বিমূর্ততা তৈরি করেছে যা সি ++ 14, সি ++ 17 এবং এর বাইরে সংযুক্ত বৈশিষ্ট্যগুলির সাথে মেলে বা ঘনিষ্ঠভাবে মেলে। এই বিমূর্ততার Abseil সংস্করণগুলি ব্যবহার করা আপনাকে এখনই এই বৈশিষ্ট্যগুলিতে অ্যাক্সেস করতে দেয়, এমনকি যদি আপনার কোডটি সি ++ 11 পোস্টের পোস্টে জীবনের জন্য প্রস্তুত না হয়।

এখানে কয়েকটি মূল সংস্থান এবং লিঙ্ক রয়েছে:

  1. মূল সাইট: https://abseil.io/
  2. https://abseil.io/docs/cpp/
  3. গিটহাব সংগ্রহস্থল: https://github.com/abseil/abseil-cpp
  4. span.hশিরোনাম এবং absl::Span<T>(array, length)টেম্পলেট শ্রেণি: https://github.com/abseil/abseil-cpp/blob/master/absl/tyype/span.h#L189

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