ডিক্লাইপ (অটো) এর কিছু ব্যবহার কী?


151

সি ++ 14-এ decltype(auto)আইডিয়ামটি চালু করা হয়েছে।

সাধারণত এর ব্যবহার হয় অনুমতি দেয় autoঘোষণা ব্যবহার করতে decltypeদেওয়া অভিব্যক্তি উপর নিয়ম

আইডিয়মের "ভাল" ব্যবহারের উদাহরণ অনুসন্ধান করে আমি কেবলমাত্র ( স্কট মায়ার্স দ্বারা ) যেমন ফাংশনটির রিটার্ন টাইপ ছাড়ের জন্য এই জাতীয় জিনিসগুলি ভাবতে পারি :

template<typename ContainerType, typename IndexType>                // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
  authenticateUser();
  return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}

অন্য কোনও উদাহরণ রয়েছে যেখানে এই নতুন ভাষার বৈশিষ্ট্যটি কার্যকর?


2
এই পোস্টে মূলত এই বাগ্ধারা এড়াতে কারণ আপনি আপনার কম্পাইলার অপ্টিমাইজেশান জন্য কম অপশন দিচ্ছেন যখন এটি ব্যবহার করার চেষ্টা করুন সুপারিশ stackoverflow.com/a/20092875/2485710
user2485710

আমি একবার decltype(auto)অনুরূপ কিছু জন্য ব্যবহার করেছি template<class U, V> decltype(auto) first(std::pair<U, V>& p) { return p.first; }, যদিও আমি তখন বুঝতে পেরেছিলাম return (p.first);যে আশ্চর্যজনকভাবে কাজ করে এমন আমার ব্যবহার করতে হবে (তবে আইআইআরসি এটি এমনকি উদ্দেশ্যযুক্ত)।
ডায়প

@ ব্যবহারকারী 2485710 নিশ্চিত নয় যে এটি বিশেষত অপ্টিমাইজেশান সম্পর্কে, দুর্ঘটনার আরও বেশি সম্ভাবনা যদি decltype(auto)প্রত্যাশার বিপরীতে কোনও কিছু অনুলিপি করা / ঘোষিত বস্তুতে স্থানান্তরিত করতে পারে।
আন্ডারস্কোর_ডি

উত্তর:


170

জেনেরিক কোডে রিটার্ন টাইপ ফরোয়ার্ডিং

জেনেরিক কোডের জন্য, আপনি যে প্রাথমিক উদাহরণ দিয়েছেন তার মতো আপনিও রিটার্নের ধরণ হিসাবে একটি রেফারেন্স পেতে ম্যানুয়ালি নির্বাচন করতে পারেন:

auto const& Example(int const& i) 
{ 
    return i; 
}

তবে জেনেরিক কোডে আপনি কোনও রেফারেন্স বা কোনও মান নিয়ে কাজ করছেন কিনা তা জেনেও আপনি কোনও রিটার্ন টাইপ পুরোপুরি ফরোয়ার্ড করতে সক্ষম হতে চান । decltype(auto)আপনাকে সেই ক্ষমতা দেয়:

template<class Fun, class... Args>
decltype(auto) Example(Fun fun, Args&&... args) 
{ 
    return fun(std::forward<Args>(args)...); 
}

পুনরাবৃত্তাকার টেম্পলেটগুলিতে রিটার্নের ধরণের কাটা বিলম্ব করছে

ইন এই Q & A- কয়েক দিন আগে, ফর্মা ইনস্ট্যান্স সময় একটি অসীম recursion যখন টেমপ্লেটের রিটার্ন টাইপ হিসাবে নির্দিষ্ট সম্মুখীন হয়েছিল decltype(iter(Int<i-1>{}))পরিবর্তে decltype(auto)

template<int i> 
struct Int {};

constexpr auto iter(Int<0>) -> Int<0>;

template<int i>
constexpr auto iter(Int<i>) -> decltype(auto) 
{ return iter(Int<i-1>{}); }

int main() { decltype(iter(Int<10>{})) a; }

decltype(auto)টেম্পলেট ইনস্ট্যান্টেশনের ধুলো স্থির হয়ে যাওয়ার পরে রিটার্ন টাইপ ছাড়ের ক্ষেত্রে বিলম্ব করতে এখানে ব্যবহৃত হয় ।

অন্যান্য ব্যবহার

আপনি decltype(auto)অন্যান্য প্রসঙ্গেও ব্যবহার করতে পারেন , যেমন স্ট্যান্ডার্ড N3936 খসড়াটিও জানিয়েছে

.1.১..4.৪ অটো স্পেসিওর [dcl.spec.auto]

1 autoএবং decltype(auto)টাইপ-স্পেসিফিক্স একটি স্থানধারক প্রকার নির্ধারণ করে যা পরে পরিবর্তিত হবে, তা হয় আরম্ভকারী থেকে ছাড়ের মাধ্যমে বা স্পষ্টভাবে স্পেসিফিকেশন দ্বারা ট্রেলিং-রিটার্ন-টাইপের মাধ্যমে। autoটাইপ-সুনিন্টি ফাই Er এছাড়াও বোঝান যে একটি ল্যামডা একটি জেনেরিক ল্যামডা ব্যবহৃত হয়।

2 ডেস্ক -স্পেসিফায়ার-সেক, টাইপ-স্পেসিফায়ার-সেক, রূপান্তর-ফাংশন-আইডি, বা ট্রেলিং-রিটার্ন-টাইপ, যেখানে এই ধরণের ডিক্লেয়ারের বৈধতা রয়েছে সেই স্থানধারক প্রকারটি কোনও ফাংশন ডিক্লেয়ারের সাথে উপস্থিত হতে পারে । যদি ফাংশন ডিক্লেয়ারারে একটি ট্রেলিং-রিটার্ন-টাইপ (8.3.5) থাকে তবে এটি ফাংশনের ঘোষিত রিটার্নের ধরণ নির্দিষ্ট করে। যদি ফাংশনটির ঘোষিত রিটার্ন টাইপটিতে কোনও স্থানধারক প্রকার থাকে তবে ফাংশনের রিটার্ন টাইপটি ফাংশনের শরীরে রিটার্নের স্টেটমেন্ট থেকে বাদ দেওয়া হয়, যদি থাকে।

খসড়াটিতে পরিবর্তনশীল সূচনা করার উদাহরণও রয়েছে:

int i;
int&& f();
auto x3a = i;                  // decltype(x3a) is int
decltype(auto) x3d = i;        // decltype(x3d) is int
auto x4a = (i);                // decltype(x4a) is int
decltype(auto) x4d = (i);      // decltype(x4d) is int&
auto x5a = f();                // decltype(x5a) is int
decltype(auto) x5d = f();      // decltype(x5d) is int&&
auto x6a = { 1, 2 };           // decltype(x6a) is std::initializer_list<int>
decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
auto *x7a = &i;                // decltype(x7a) is int*
decltype(auto)*x7d = &i;       // error, declared type is not plain decltype(auto)

17
(i)বনাম এর বিভেদ আচরণ কি iসি ++ 14 এ কোনও নতুন জিনিস?
ড্যানভিল

14
@ ড্যানভিল decltype(expr)এবং decltype((expr))ইতিমধ্যে সি ++ 11-এ পৃথক, এটি আচরণকে সাধারণীকরণ করে।
TemplateRex

13
আমি এটি এখনই শিখেছি, একটি ভয়াবহ নকশার সিদ্ধান্তের মতো মনে হচ্ছে ... প্রথম বন্ধনীর সিনট্যাক্স অর্থের সাথে একটি সময়িক সংজ্ঞা যুক্ত হয়েছে।
কাহলর

যে উদাহরণটি সর্বদা এই ঘৃণাকে প্ররোচিত করে তা হ'ল ওয়ান লাইনার ফাইল-টু-স্ট্রিং সিনট্যাক্স (সেই লিঙ্কটিতেও উল্লেখ করা হয়েছে)। এর প্রতিটি অংশই পিছিয়ে পড়েছে বলে মনে হচ্ছে। আপনি সম্ভবত অস্পষ্টতা আশা করতে পারেন না, এবং বাধ্যতামূলকভাবে কোনও নমুনা থেকে অপ্রয়োজনীয় প্রথম বন্ধনী অপসারণ করতে পারেন; আপনি SFINAE অনুযায়ী নির্মূল প্রক্রিয়া দ্বারা অস্পষ্টতা সমাধানের প্রত্যাশা করবেন তবে ঘোষণা ছাড়া অন্য প্রার্থীরা আগাম নির্মূল হয়ে যাবে (এসএফ হ'ল এই); এবং হতাশায় আপনি নির্বিচারে প্যারেনস অস্পষ্টতার সমাধানের চিন্তাভাবনাগুলি সঙ্কলন করার সাথে সাথেই এগিয়ে যেতে পারেন তবে তারা এটি প্রবর্তন করে। আমি কল্পনা করেছি CS101 অধ্যাপকদের সর্বাধিক উদ্বেগজনক।
জন পি

@ টেম্পলেটআরেক্স: রেফারেন্সযুক্ত প্রশ্নে রিটার্নের ধরণের রেজোলিউশনটি বিলম্বিত করার বিষয়ে: যতদূর আমি দেখতে পাচ্ছি, নির্দিষ্ট দৃশ্যে একটি সাধারণ autoকাজটি ঠিক তেমনি করেই করতে পারত, ফলাফল যেভাবেই মান দিয়ে ফিরে আসবে ... বা আমি মিস করেছি? কিছু?
অ্যাকনকাগুয়া

36

এখান থেকে স্টাফ উদ্ধৃত :

  • decltype(auto)ফরোয়ার্ডিং ফাংশন এবং অনুরূপ মোড়কের রিটার্নের ধরণের জন্য মূলত দরকারী , যেখানে আপনি টাইপ করতে চান এমন কোনও এক্সপ্রেশনটি ঠিক "ট্র্যাক" করতে চান।

  • উদাহরণস্বরূপ, নীচে কার্যাদি দেওয়া:


   string  lookup1();
   string& lookup2();

  • সি ++ 11 এ আমরা নিম্নলিখিত র‍্যাপার ফাংশনগুলি লিখতে পারি যা রিটার্নের ধরণের রেফারেন্স-নেসটি মনে রাখে:

   string  look_up_a_string_1() { return lookup1(); }
   string& look_up_a_string_2() { return lookup2(); }

  • সি ++ এ, আমরা এটি স্বয়ংক্রিয় করতে পারি:

   decltype(auto) look_up_a_string_1() { return lookup1(); }
   decltype(auto) look_up_a_string_2() { return lookup2(); }

  • যাইহোক, এর decltype(auto)বাইরেও বহুল ব্যবহৃত বৈশিষ্ট্য হওয়ার উদ্দেশ্যে নয়।

  • বিশেষত, যদিও এটি স্থানীয় ভেরিয়েবলগুলি ঘোষণার জন্য ব্যবহার করা যেতে পারে , এটি করা কেবলমাত্র একটি অ্যান্টিপ্যাটার্ন কারণ স্থানীয় ভেরিয়েবলের রেফারেন্স-নেস আরম্ভের অভিব্যক্তির উপর নির্ভর করে না।

  • এছাড়াও, আপনি কীভাবে রিটার্নের বিবৃতি লিখবেন তা সংবেদনশীল।

  • উদাহরণস্বরূপ, নীচের দুটি ফাংশনটির ভিন্ন ভিন্ন রিটার্ন রয়েছে:


   decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; }
   decltype(auto) look_up_a_string_2() { auto str = lookup2(); return(str); }

  • প্রথম রিটার্ন string, দ্বিতীয় রিটার্ন string&, যা স্থানীয় ভেরিয়েবলের একটি রেফারেন্স str

প্রস্তাবনা থেকে আপনি আরও লক্ষ্যযুক্ত ব্যবহার দেখতে পাবেন।


3
শুধু autoফেরতের জন্য ব্যবহার করবেন না কেন ?
BЈовић

@ বিও সাধারণ রিটার্নের ধরণের ছাড় (যেমন, autoরিটার্ন) দিয়েও কাজ করতে পারে তবে ওপি বিশেষত এর ব্যবহারের জন্য জিজ্ঞাসা করেছিল decltype(auto)
101010

3
যদিও প্রশ্নটি এখনও প্রাসঙ্গিক। রিটার্ন টাইপ কেমন হবে auto lookup_a_string() { ... } ? এটি কি সর্বদা একটি অ-রেফারেন্স টাইপ হয়? এবং সেইজন্য auto lookup_a_string() ->decltype(auto) { ... }রেফারেন্সগুলি (কিছু ক্ষেত্রে) ফেরত দেওয়ার অনুমতি দেওয়ার জন্য জোর করা দরকার?
অ্যারন ম্যাকডেইড

@ অ্যারোনএমসিডিএইড ডিডুকটিবলকে autoমান টেম্পলেট দ্বারা পাসের মেয়াদে সংজ্ঞায়িত করা হয়, সুতরাং হ্যাঁ এটি কোনও রেফারেন্স হতে পারে না। autoঅবশ্যই অপেক্ষা করুন অবশ্যই একটি রেফারেন্স সহ কিছু হতে পারে।
কৌতূহলী

4
উল্লেখযোগ্য একটি অতিরিক্ত উদাহরণ হ'ল একটি এর উপাদানটি ফেরত দেওয়া std::vector। বলুন তো আছে template<typename T> struct S { auto & operator[](std::size_t i) { return v[i]; } std::vector<T> v; }। তারপরে S<bool>::operator[]বিশেষত্বের কারণে ঝুঁকির রেফারেন্স ফিরে আসবে std::vector<bool>। রিটার্নের decltype(auto)ধরণটি এই সমস্যাটিকে পরিপূর্ণ করে তোলা।
জোফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.