ইনিশিয়াল_লিস্ট এবং মুভি শব্দার্থক


98

আমি কি উপাদানগুলির বাইরে সরানোর অনুমতি দিচ্ছি std::initializer_list<T>?

#include <initializer_list>
#include <utility>

template<typename T>
void foo(std::initializer_list<T> list)
{
    for (auto it = list.begin(); it != list.end(); ++it)
    {
        bar(std::move(*it));   // kosher?
    }
}

যেহেতু std::intializer_list<T>বিশেষ সংকলক মনোযোগ প্রয়োজন এবং সি ++ স্ট্যান্ডার্ড লাইব্রেরির সাধারণ ধারকগুলির মতো মূল্য শব্দার্থবিজ্ঞান নেই, তাই আমি দুঃখিত ও জিজ্ঞাসার চেয়ে নিরাপদ থাকব।


মূল ভাষাটি সংজ্ঞায়িত করে যে অবজেক্টটি একটি initializer_list<T>দ্বারা নির্ধারিত হয়েছে নন- কনস্টাস্ট। পছন্দ, অবজেক্ট initializer_list<int>বোঝায় int। তবে আমি মনে করি এটি একটি ত্রুটি - এটি উদ্দেশ্যযুক্ত যে সংকলকরা কেবলমাত্র পঠন মেমরির মধ্যে একটি তালিকা স্থিতিশীলভাবে বরাদ্দ করতে পারে।
জোহানেস স্কাউব -

উত্তর:


92

না, এটি ইচ্ছাকৃতভাবে কাজ করবে না; আপনি এখনও কপি পাবেন। আমি এতে অবাক হয়েছি, যেহেতু আমি ভেবেছিলাম যে initializer_listতারা না হওয়া অবধি অস্থায়ী সংস্থাগুলির ব্যবস্থা রাখার জন্য অস্তিত্ব ছিল move

beginএবং ফিরে আসার endজন্য , সুতরাং আপনার কোডের ফলাফল - একটি অপরিবর্তনীয় মূল্যের রেফারেন্স। এই জাতীয় অভিব্যক্তি অর্থবহ থেকে সরানো যায় না। এটি টাইপের কোনও ফাংশন প্যারামিটারে আবদ্ধ হবে কারণ মূল্যবোধগুলি লভ্যালু রেফারেন্সগুলিতে আবদ্ধ হয় এবং আপনি এখনও অনুলিপি শব্দার্থবিজ্ঞান দেখতে পাবেন।initializer_listconst T *moveT const &&T const &

সম্ভবত এর কারণ তাই সংকলক initializer_listস্ট্যাটিক্যালি-ইনিশিয়েলাইজড ধ্রুবক তৈরি করতে বেছে নিতে পারে , তবে মনে হয় এটির ধরণটি তৈরি করা পরিষ্কার করা ভাল initializer_listবা const initializer_listসংকলকটির বিবেচনার ভিত্তিতে, সুতরাং ব্যবহারকারী কোনও constজবাবদিহি করতে বা পরিবর্তনযোগ্য কিনা তা জানেনা থেকে ফলাফল beginএবং end। তবে এটি কেবল আমার পেটের অনুভূতি, সম্ভবত আমি ভুল হওয়ার কোনও ভাল কারণ রয়েছে।

আপডেট: কেবল স্থানান্তরিত প্রকারের সমর্থনের জন্য আমি একটি আইএসও প্রস্তাব লিখেছি initializer_list। এটি শুধুমাত্র প্রথম খসড়া, এবং এটি এখনও কোথাও বাস্তবায়িত হয়নি, তবে সমস্যার আরও বিশ্লেষণের জন্য আপনি এটি দেখতে পারেন can


11
যদি এটি স্পষ্ট না হয় তবে এর অর্থ এখনও std::moveউত্পাদনশীল না থাকলে ব্যবহার করা নিরাপদ। ( T const&&মুভ কনস্ট্রাক্টরদের ব্যতীত))
ড্যান্টন

আমি মনে করি না আপনি পুরো যুক্তিটি const std::initializer_list<T>কেবল বা std::initializer_list<T>এমনভাবে তৈরি করতে পারেন যা প্রায়শই অবাক করে না। বিবেচনা করুন যে কলের প্রতিটি যুক্তি initializer_listহয় constবা না হতে পারে এবং এটি কলারের প্রসঙ্গে জানা যায়, তবে সংকলককে অবশ্যই কলির প্রসঙ্গে কোডের একটি সংস্করণ উত্পন্ন করতে হবে (অর্থাত্ এর অভ্যন্তরে fooআর্গুমেন্ট সম্পর্কে কিছুই জানে না যে কলারটি চলেছে)
ডেভিড রডগ্রিজেজ - ড্রিবাস

4
@ ডেভিড: ভাল কথা, তবে std::initializer_list &&একটি অ-রেফারেন্স ওভারলোডের প্রয়োজন পরেও ওভারলোড কিছু করার পক্ষে এটি কার্যকর হবে। আমি মনে করি এটি বর্তমান পরিস্থিতির চেয়ে আরও বিভ্রান্তিকর হবে, যা ইতিমধ্যে খারাপ।
পোটোসওয়টার

4
@JBJansen- এটি প্রায় হ্যাক করা যায় না। সেই কোডটি আর্ট ইনিশিয়ালাইজার_লিস্টটি সম্পাদন করার কথাটি আমি ঠিক দেখতে পাচ্ছি না, তবে ব্যবহারকারী হিসাবে আপনার এটি থেকে সরানোর জন্য প্রয়োজনীয় অনুমতি নেই। নিরাপদ কোড এটি করবে না।
পোটোটোওয়াতর

4
@ পোটাটোসওয়াতর, দেরিতে মন্তব্য, তবে প্রস্তাবটির অবস্থা কী what's এটির কোনও দূরবর্তী সুযোগ কি এটি সি ++ ২০ এ পরিণত করতে পারে?
WhiZTiM

20
bar(std::move(*it));   // kosher?

আপনার ইচ্ছা মতো নয় Not আপনি কোনও constবস্তুকে সরিয়ে নিতে পারবেন না । এবং std::initializer_listশুধুমাত্র constএর উপাদানগুলিতে অ্যাক্সেস সরবরাহ করে। ধরণ তাই itহয় const T *

আপনার কল করার প্রয়াসের std::move(*it)ফলে কেবলমাত্র একটি এল-মান হবে। IE: একটি অনুলিপি

std::initializer_listস্থির মেমরি রেফারেন্স । ক্লাসটি এটাই। আপনি স্থির মেমরি থেকে সরাতে পারবেন না , কারণ চলাচলে বোঝানো হয় এটি পরিবর্তন করা। আপনি কেবল এটি থেকে অনুলিপি করতে পারেন।


একটি কনস্ট কনভ্যালু এখনও একটি এক্সাল্যু এবং initializer_listএটি প্রয়োজনীয় হলে স্ট্যাকের উল্লেখ করে। (যদি বিষয়বস্তুগুলি স্থির না হয় তবে এটি এখনও থ্রেড-নিরাপদ))
পটোটোসওয়টার

5
@ পোটাটোসওয়টার: আপনি একটি ধ্রুবক বস্তু থেকে সরাতে পারবেন না। initializer_listবস্তু নিজেই একটি xvalue হতে পারে, কিন্তু এটা বিষয়বস্তু (প্রকৃত মূল্যবোধের এটি স্থানটিকে অ্যারে) রয়েছে const, কারণ যারা বিষয়বস্তু স্ট্যাটিক মান হতে পারে। আপনি কেবল একটি বিষয়বস্তু থেকে সরানো যাবে না initializer_list
নিকল বোলাস

আমার উত্তর এবং এর আলোচনা দেখুন। তিনি একটি constমূল্যমান উত্পাদিত, অবনমিত পুনরাবৃত্তি স্থানান্তরিত করেছেন । moveঅর্থহীন হতে পারে, তবে এটি আইনী এবং এমন কোনও পরামিতি ঘোষণা করাও সম্ভব যা কেবল এটি গ্রহণ করে। যদি কোনও নির্দিষ্ট ধরণের স্থানান্তর করা কোনও অনিঃপত্তি হয়ে থাকে তবে এটি সঠিকভাবে কাজ করতে পারে।
পোটোসওয়টার

4
@ পোটাটোসওয়াতর: সি ++ 11 স্ট্যান্ডার্ডটি অনেকগুলি ভাষা ব্যয় করে তা নিশ্চিত করে যে অস্থায়ী বস্তুগুলি বাস্তবে সরানো হয় না আপনি যদি না ব্যবহার করেন std::move। এটি নিশ্চিত করে যে কোনও মুভিং অপারেশন ঘটলে আপনি পরিদর্শন থেকে বলতে পারবেন, যেহেতু এটি উত্স এবং গন্তব্য উভয়কেই প্রভাবিত করে (আপনি চান না যে এটি নামকৃত বস্তুর জন্য স্পষ্টভাবে ঘটুক)। এ কারণে, আপনি std::moveযদি এমন জায়গায় ব্যবহার করেন যেখানে কোনও মুভ অপারেশন ঘটে না (এবং যদি আপনার কোনও constএক্সওয়ালু থাকে তবে কোনও আসল চলাচল ঘটবে না ), তবে কোডটি বিভ্রান্তিকর। আমি মনে করি std::moveকোনও constবস্তুর কাছে কল করা ভুল ।
নিকল বোলাস

4
হতে পারে, তবে আমি বিভ্রান্তিকর কোডের সম্ভাবনার চেয়ে নিয়মগুলিতে এখনও কিছু কম ব্যতিক্রম গ্রহণ করব। যাইহোক, ঠিক এই কারণেই আমি বৈধ হওয়া সত্ত্বেও "না" জবাব দিয়েছি, এবং ফলাফলটি কেবলমাত্র একটি কনস্টাল লভালু হিসাবে আবদ্ধ হবে এমনকী এটি একটি জালিয়াতি। সত্যি কথা বলতে, আমি ইতিমধ্যে const &&ম্যানেজড পয়েন্টার সহ একটি আবর্জনা-সংগৃহীত শ্রেণিতে একটি সংক্ষিপ্ত ফ্লার্টিং করেছি , যেখানে প্রাসঙ্গিক সবকিছু পরিবর্তনীয় এবং চলমান পয়েন্টার পরিচালনাকে সরিয়ে নিয়েছিল তবে এতে থাকা মানকে প্রভাবিত করেনি। সবসময় জটিল প্রান্তের কেস থাকে: v)।
20:31

3

এটি উল্লিখিত হিসাবে কাজ করবে না, কারণ list.begin()টাইপ আছে const T *, এবং ধ্রুবক বস্তু থেকে আপনি সরানোর কোনও উপায় নেই। ভাষা ডিজাইনাররা সম্ভবত এটি তৈরি করেছিলেন যাতে প্রাথমিককরণের তালিকাগুলিকে উদাহরণস্বরূপ স্ট্রিং ধ্রুবকগুলির জন্য অন্তর্ভুক্ত থাকতে পারে, যেখান থেকে এটি সরানো অনুচিত।

তবে আপনি যদি এমন পরিস্থিতিতে থাকেন যে আপনি যদি জানেন যে প্রারম্ভিক তালিকার মধ্যে মূল্যের ভাব রয়েছে (বা আপনি ব্যবহারকারীকে সেগুলি লিখতে বাধ্য করতে চান) তবে একটি কৌশল আছে যা এটি কার্যকর করবে (সুমেন্টের উত্তরের দ্বারা অনুপ্রেরণা পেয়েছিলাম) এটি, তবে সমাধানটি এর চেয়ে সহজতর উপায়)। আপনি প্রয়োজন initialiser তালিকা সঞ্চিত উপাদান হতে না Tমান, কিন্তু যে encapsulate মান T&&। তারপরেও যদি সেই মানগুলি নিজেরাই constযোগ্য হয় তবে তারা এখনও একটি পরিবর্তনযোগ্য মূল্য পুনরুদ্ধার করতে পারে।

template<typename T>
  class rref_capture
{
  T* ptr;
public:
  rref_capture(T&& x) : ptr(&x) {}
  operator T&& () const { return std::move(*ptr); } // restitute rvalue ref
};

এখন initializer_list<T>যুক্তি ঘোষণার পরিবর্তে আপনি একটি initializer_list<rref_capture<T> >যুক্তি ঘোষণা করুন । এখানে একটি দৃ concrete় উদাহরণ রয়েছে, std::unique_ptr<int>স্মার্ট পয়েন্টারগুলির একটি ভেক্টরকে জড়িত করে, যার জন্য কেবল পদার্থবিজ্ঞানের সংজ্ঞা দেওয়া হয় (যাতে এই বিষয়গুলি নিজেরাই আর কোনও প্রাথমিকের তালিকায় সংরক্ষণ করা যায় না); তবুও নীচের প্রারম্ভক তালিকাটি সমস্যা ছাড়াই সংকলন করে।

#include <memory>
#include <initializer_list>
class uptr_vec
{
  typedef std::unique_ptr<int> uptr; // move only type
  std::vector<uptr> data;
public:
  uptr_vec(uptr_vec&& v) : data(std::move(v.data)) {}
  uptr_vec(std::initializer_list<rref_capture<uptr> > l)
    : data(l.begin(),l.end())
  {}
  uptr_vec& operator=(const uptr_vec&) = delete;
  int operator[] (size_t index) const { return *data[index]; }
};

int main()
{
  std::unique_ptr<int> a(new int(3)), b(new int(1)),c(new int(4));
  uptr_vec v { std::move(a), std::move(b), std::move(c) };
  std::cout << v[0] << "," << v[1] << "," << v[2] << std::endl;
}

একটি প্রশ্নের উত্তরের দরকার আছে: যদি প্রাথমিকের তালিকার উপাদানগুলি সত্য মূল্য থাকে (উদাহরণস্বরূপ তারা xvalue হয়) তবে ভাষাটি কি নিশ্চিত করে যে সংশ্লিষ্ট টেম্পোরারিগুলির আজীবন তারা যে বিন্দুতে ব্যবহৃত হয়েছে সেখানে প্রসারিত হবে? সত্যই, আমি মনে করি না যে প্রমিতের 8.5 প্রাসঙ্গিক বিষয়টি এই বিষয়টিকে মোটেই সম্বোধন করে। যাইহোক, ১.৯: ১০ পড়লে মনে হবে প্রাসঙ্গিক পূর্ণ-এক্সপ্রেশনটি সব ক্ষেত্রেই ইনিশিয়ালার তালিকার ব্যবহারকে অন্তর্ভুক্ত করে, সুতরাং আমি মনে করি যে মূল্যবোধের রেফারেন্সগুলি ঝুঁকির কোনও আশঙ্কা নেই।


স্ট্রিং ধ্রুবক? পছন্দ "Hello world"? আপনি যদি সেগুলি থেকে সরে যান তবে আপনি কেবল একটি পয়েন্টার অনুলিপি করুন (বা একটি রেফারেন্স বাঁধুন)।
ডায়প করুন

4
"একটি প্রশ্নের উত্তর দরকার নেই" ভিতরে সূচনাকারীরা {..}ফাংশন প্যারামিটারের রেফারেন্সগুলিতে আবদ্ধ rref_capture। এটি তাদের আজীবন প্রসারিত করে না, তারা এখনও তৈরি করেছে এমন পূর্ণ-প্রকাশের শেষে ধ্বংস হয়ে গেছে।
dyp

প্রতি টিসি এর অন্য উত্তর থেকে মন্তব্য: আপনি কন্সট্রাকটর একাধিক overloads থাকে, তাহলে মোড়ানো std::initializer_list<rref_capture<T>>- বলে, আপনার পছন্দসই কিছু রূপান্তর বৈশিষ্ট্য মধ্যে std::decay_t- অবাঞ্ছিত সিদ্ধান্তগ্রহণ ব্লক করতে।
আনস্ল্যান্ডার মনিকা

2

আমি ভেবেছিলাম এটি একটি কাজের জন্য একটি যুক্তিসঙ্গত প্রারম্ভিক বিন্দু প্রস্তাব দেওয়া শিক্ষণীয় হতে পারে।

মন্তব্য ইনলাইন।

#include <memory>
#include <vector>
#include <array>
#include <type_traits>
#include <algorithm>
#include <iterator>

template<class Array> struct maker;

// a maker which makes a std::vector
template<class T, class A>
struct maker<std::vector<T, A>>
{
  using result_type = std::vector<T, A>;

  template<class...Ts>
  auto operator()(Ts&&...ts) const -> result_type
  {
    result_type result;
    result.reserve(sizeof...(Ts));
    using expand = int[];
    void(expand {
      0,
      (result.push_back(std::forward<Ts>(ts)),0)...
    });

    return result;
  }
};

// a maker which makes std::array
template<class T, std::size_t N>
struct maker<std::array<T, N>>
{
  using result_type = std::array<T, N>;

  template<class...Ts>
  auto operator()(Ts&&...ts) const
  {
    return result_type { std::forward<Ts>(ts)... };
  }

};

//
// delegation function which selects the correct maker
//
template<class Array, class...Ts>
auto make(Ts&&...ts)
{
  auto m = maker<Array>();
  return m(std::forward<Ts>(ts)...);
}

// vectors and arrays of non-copyable types
using vt = std::vector<std::unique_ptr<int>>;
using at = std::array<std::unique_ptr<int>,2>;


int main(){
    // build an array, using make<> for consistency
    auto a = make<at>(std::make_unique<int>(10), std::make_unique<int>(20));

    // build a vector, using make<> because an initializer_list requires a copyable type  
    auto v = make<vt>(std::make_unique<int>(10), std::make_unique<int>(20));
}

প্রশ্নটি ছিল যদি initializer_listকোনওটি স্থানান্তরিত হতে পারে তবে কারও কর্মক্ষেত্র রয়েছে কিনা তা নয়। তদতিরিক্ত, এর প্রধান বিক্রয় বিন্দুটি initializer_listহ'ল এটি কেবল উপাদান ধরণের ক্ষেত্রে তত্পর হয়, উপাদানগুলির সংখ্যা নয়, এবং তাই প্রাপককেও টেম্পলেট করা প্রয়োজন হয় না - এবং এটি পুরোপুরি হারাতে থাকে।
আন্ডারস্কোর_১

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

অবশ্যই, এটি পাঠকদের জন্য সত্যই সহায়তা করতে পারে যারা এর মতো কিছু চান initializer_listতবে এটি যে সমস্ত প্রতিবন্ধকতাগুলির পক্ষে এটি কার্যকর তা কার্যকর হয় না। :)
আন্ডারস্কোর_২

@ বৌদ্ধ_আমি কোন বাধাটিকে উপেক্ষা করেছি?
রিচার্ড হজস

আমার সমস্ত অর্থ হ'ল initializer_list(সংকলক যাদুর মাধ্যমে) উপাদানগুলির সংখ্যার উপর টেমপ্লেট ফাংশনগুলি এড়ানো এড়ানো যায়, এমন কিছু যা অভ্যন্তরীণভাবে অ্যারে এবং / বা ভেরিয়েডিক ফাংশনগুলির উপর ভিত্তি করে বিকল্পগুলির দ্বারা প্রয়োজনীয় হয়, সুতরাং যেগুলি পরে ব্যবহারযোগ্য সেগুলিগুলির পরিসীমা সীমাবদ্ধ করে। আমার বোঝার দ্বারা, এটি হ'ল যথাযথভাবে থাকার অন্যতম মূল যুক্তি initializer_list, সুতরাং এটি উল্লেখ করার মতো বলে মনে হয়েছিল।
আন্ডারস্কোর_ডি

0

ইতিমধ্যে উত্তর হিসাবে এটি বর্তমান মানকটিতে অনুমোদিত নয় বলে মনে হচ্ছে । প্রারম্ভিকের তালিকার পরিবর্তে ফাংশনটিকে ভ্যারিয়্যাডিক হিসাবে সংজ্ঞায়িত করে অনুরূপ কিছু অর্জনের জন্য এখানে আরও কাজ করার সুযোগ রয়েছে।

#include <vector>
#include <utility>

// begin helper functions

template <typename T>
void add_to_vector(std::vector<T>* vec) {}

template <typename T, typename... Args>
void add_to_vector(std::vector<T>* vec, T&& car, Args&&... cdr) {
  vec->push_back(std::forward<T>(car));
  add_to_vector(vec, std::forward<Args>(cdr)...);
}

template <typename T, typename... Args>
std::vector<T> make_vector(Args&&... args) {
  std::vector<T> result;
  add_to_vector(&result, std::forward<Args>(args)...);
  return result;
}

// end helper functions

struct S {
  S(int) {}
  S(S&&) {}
};

void bar(S&& s) {}

template <typename T, typename... Args>
void foo(Args&&... args) {
  std::vector<T> args_vec = make_vector<T>(std::forward<Args>(args)...);
  for (auto& arg : args_vec) {
    bar(std::move(arg));
  }
}

int main() {
  foo<S>(S(1), S(2), S(3));
  return 0;
}

ভেরিয়াদিক টেম্পলেটগুলি আরম্ভকারী_ তালিকার বিপরীতে যথাযথভাবে আর-মান উল্লেখগুলি পরিচালনা করতে পারে।

এই উদাহরণ কোডে, আমি আসল কোডের অনুরূপ তৈরি করতে ভেরিয়েডিক আর্গুমেন্টগুলিকে ভেক্টরে রূপান্তরিত করতে ছোট সহায়ক সহায়ক ফাংশনগুলির একটি সেট ব্যবহার করেছি। তবে অবশ্যই আপনি পরিবর্তে পরিবর্তে ভেরিয়াদিক টেম্পলেটগুলির সাথে একটি পুনরাবৃত্ত ফাংশন লিখতে পারেন।


প্রশ্নটি ছিল যদি initializer_listকোনওটি স্থানান্তরিত হতে পারে তবে কারও কর্মক্ষেত্র রয়েছে কিনা তা নয়। তদতিরিক্ত, এর প্রধান বিক্রয় বিন্দুটি initializer_listহ'ল এটি কেবল উপাদান ধরণের ক্ষেত্রে তত্পর হয়, উপাদানগুলির সংখ্যা নয়, এবং তাই প্রাপককেও টেম্পলেট করা প্রয়োজন হয় না - এবং এটি পুরোপুরি হারাতে থাকে।
আন্ডারস্কোর_১

0

আমার কাছে অনেকগুলি সহজ বাস্তবায়ন রয়েছে যা একটি মোড়কের ক্লাস ব্যবহার করে যা উপাদানগুলিকে সরানোর অভিপ্রায় চিহ্নিত করতে ট্যাগ হিসাবে কাজ করে। এটি একটি সংকলন-সময় ব্যয়।

মোড়কের ক্লাসটি ব্যবহার করার জন্য ডিজাইন করা হয়েছে যেভাবে std::moveব্যবহৃত হয়, কেবল এটির std::moveসাথে প্রতিস্থাপন করুন move_wrapperতবে এর জন্য সি ++ 17 প্রয়োজন requires পুরানো চশমা জন্য, আপনি একটি অতিরিক্ত নির্মাতা পদ্ধতি ব্যবহার করতে পারেন।

আপনাকে বিল্ডার পদ্ধতি / নির্মাতারা লিখতে হবে যা অভ্যন্তরের মোড়কের ক্লাস গ্রহণ করে এবং ততক্ষণে initializer_listউপাদানগুলিকে সরিয়ে দেয়।

আপনার যদি সরানোর পরিবর্তে কিছু উপাদান অনুলিপি করার প্রয়োজন হয় তবে তা অনুলিপি করার আগে একটি অনুলিপি তৈরি করুন initializer_list

কোডটি স্ব-ডকুমেন্টেড হওয়া উচিত।

#include <iostream>
#include <vector>
#include <initializer_list>

using namespace std;

template <typename T>
struct move_wrapper {
    T && t;

    move_wrapper(T && t) : t(move(t)) { // since it's just a wrapper for rvalues
    }

    explicit move_wrapper(T & t) : t(move(t)) { // acts as std::move
    }
};

struct Foo {
    int x;

    Foo(int x) : x(x) {
        cout << "Foo(" << x << ")\n";
    }

    Foo(Foo const & other) : x(other.x) {
        cout << "copy Foo(" << x << ")\n";
    }

    Foo(Foo && other) : x(other.x) {
        cout << "move Foo(" << x << ")\n";
    }
};

template <typename T>
struct Vec {
    vector<T> v;

    Vec(initializer_list<T> il) : v(il) {
    }

    Vec(initializer_list<move_wrapper<T>> il) {
        v.reserve(il.size());
        for (move_wrapper<T> const & w : il) {
            v.emplace_back(move(w.t));
        }
    }
};

int main() {
    Foo x{1}; // Foo(1)
    Foo y{2}; // Foo(2)

    Vec<Foo> v{Foo{3}, move_wrapper(x), Foo{y}}; // I want y to be copied
    // Foo(3)
    // copy Foo(2)
    // move Foo(3)
    // move Foo(1)
    // move Foo(2)
}

0

একটি ব্যবহার করার পরিবর্তে std::initializer_list<T>, আপনি আপনার যুক্তিটিকে অ্যারের মূল মূল্য উল্লেখ হিসাবে ঘোষণা করতে পারেন:

template <typename T>
void bar(T &&value);

template <typename T, size_t N>
void foo(T (&&list)[N] ) {
   std::for_each(std::make_move_iterator(std::begin(list)),
                 std::make_move_iterator(std::end(list)),
                 &bar);
}

void baz() {
   foo({std::make_unique<int>(0), std::make_unique<int>(1)});
}

উদাহরণটি দেখুন std::unique_ptr<int>: https://gcc.godbolt.org/z/2uNxv6


-1

সিপিটিউথগুলিতেin<T> বর্ণিত আইডিয়ামটি বিবেচনা করুন । ধারণাটি রান-টাইমে লভ্যালু / মূল্য নির্ধারণ করা এবং তারপরে কল মুভ বা অনুলিপি-নির্ধারণ করা। প্রারম্ভিক_লিস্টের সরবরাহকৃত স্ট্যান্ডার্ড ইন্টারফেসটি কনস্ট রেফারেন্স হলেও মান / লভ্যালু সনাক্ত করবে।in<T>


4
সংকলকটি ইতিমধ্যে এটি জানলে আপনি কেন রানটাইমে মান বিভাগটি নির্ধারণ করতে চান?
ফ্রেডওভারফ্লো

4
দয়া করে ব্লগটি পড়ুন এবং আপনার মতামত না থাকলে বা আরও ভাল বিকল্প থাকলে আমাকে একটি মন্তব্য দিন। সংকলকটি মান বিভাগটি জানলেও, প্রারম্ভক_সামগ্রী এটি সংরক্ষণ করে না কারণ এতে কেবল কনট পুনরুক্তি রয়েছে। সুতরাং আপনি যখন ইনিশিয়াল_লিস্টটি নির্মাণ করবেন তখন এটির মান বিভাগ "ক্যাপচার" করতে হবে এবং ফাংশনটি এটি যেমন ইচ্ছা তেমন ব্যবহার করতে পারে।
সুমন্ত

5
এই উত্তরটি লিঙ্কটি অনুসরণ না করে মূলত অকেজো, এবং এসও উত্তরগুলি লিঙ্কগুলি অনুসরণ না করে কার্যকর হওয়া উচিত।
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

4
@ সুমান্ট [অন্য কোথাও কোনও অভিন্ন পোস্ট থেকে আমার মন্তব্যটি অনুলিপি করে] কি সেই হিংস্র জগাখিচুড়ি কার্য সম্পাদন বা মেমরির ব্যবহারে আসলে কোনও পরিমাপযোগ্য সুবিধা সরবরাহ করে এবং যদি তাই হয় তবে পর্যাপ্ত পরিমাণে এই জাতীয় সুবিধাগুলি পর্যাপ্তরূপে এটি কতটা ভয়াবহ দেখায় তা উপস্থাপন করতে এবং এটি সত্য যে এটি করার চেষ্টা করছে তা নির্ধারণ করতে প্রায় এক ঘন্টা সময় নেয়? আমি এটা সন্দেহ করি।
আন্ডারস্কোর_ডে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.