স্ট্যান্ড :: ফলাফল_ এবং ডিক্লাইপ টাইপের মধ্যে পার্থক্য


100

std::result_ofসি ++ 0 এক্স এর প্রয়োজনীয়তা বুঝতে আমার কিছুটা সমস্যা হয় । যদি আমি সঠিকভাবে বুঝতে পারি, result_ofতবে নির্দিষ্ট ধরণের পরামিতিগুলির সাথে ফাংশন অবজেক্টের অনুরোধের ফলাফলটি প্রাপ্ত করতে ব্যবহৃত হয়। উদাহরণ স্বরূপ:

template <typename F, typename Arg>
typename std::result_of<F(Arg)>::type
invoke(F f, Arg a)
{
    return f(a);
}

নিম্নলিখিত কোডের সাথে আমি সত্যই পার্থক্যটি দেখতে পাচ্ছি না:

template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(f(a)) //uses the f parameter
{
    return f(a);
}

বা

template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(F()(a)); //"constructs" an F
{
    return f(a);
}

এই দুটি সমাধানের সাহায্যে আমি দেখতে পাচ্ছি কেবল আমাদের সমস্যাটি:

  • ডিকটিপকে পাশ করা অভিব্যক্তিটিতে এটি ব্যবহার করার জন্য ফান্টারের একটি উদাহরণ রয়েছে।
  • ফান্টাকারের জন্য একটি নির্ধারিত কনস্ট্রাক্টর জানুন।

আমি কি এই ভেবেই ঠিক আছি যে এর মধ্যে একমাত্র পার্থক্য decltypeএবং result_ofএটিই প্রথমটির একটি অভিব্যক্তি প্রয়োজন যেখানে দ্বিতীয়টি নেই?

উত্তর:


86

result_ofছিল বুস্ট চালু করুন, এবং তারপর অন্তর্ভুক্ত TR1 মধ্যে , এবং পরিশেষে সি ++ 0x হবে। অতএব result_ofএকটি সুবিধা রয়েছে যা পিছনে সামঞ্জস্যপূর্ণ (উপযুক্ত গ্রন্থাগারের সাথে)।

decltype সি ++ 0 এক্স এর সম্পূর্ণ নতুন জিনিস, এটি কেবল কোনও ফাংশনের প্রকারের জন্য সীমাবদ্ধ করে না এবং এটি একটি ভাষা বৈশিষ্ট্য।


যাইহোক, জিসিসি 4.5 তে, result_ofএর শর্তাবলী প্রয়োগ করা হয় decltype:

  template<typename _Signature>
    class result_of;

  template<typename _Functor, typename... _ArgTypes>
    struct result_of<_Functor(_ArgTypes...)>
    {
      typedef
        decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) )
        type;
    };

4
আমি যতদূর বুঝতে পেরেছি decltypeকুশ্রী তবে আরও শক্তিশালী। result_ofকল করার জন্য শুধুমাত্র সেই ধরণের জন্য ব্যবহার করা যেতে পারে এবং এর জন্য আর্গুমেন্ট হিসাবে ধরণের প্রয়োজন। উদাহরণস্বরূপ, আপনি result_ofএখানে ব্যবহার করতে পারবেন না : template <typename T, typename U> auto sum( T t, U u ) -> decltype( t + u );যদি আর্গুমেন্টগুলি গাণিতিক ধরণের হতে পারে (এমন কোনও ফাংশন নেই Fযা আপনি F(T,U)প্রতিনিধিত্ব করতে সংজ্ঞায়িত করতে পারেন t+uuser ব্যবহারকারীর সংজ্ঞায়িত প্রকারের জন্য আপনি যা করতে পারেন। একইভাবে (আমি এটির সাথে সত্যিই খেলিনি)) আমি কল্পনা করি সদস্য পদ্ধতিতে কলগুলি result_ofবাইন্ডার বা
— ল্যাম্বডাস

4
একটি নোট, ডিক্লাইপটির সাথে আফাকের সাথে ফাংশনটি কল করার জন্য আর্গুমেন্টগুলির প্রয়োজন, সুতরাং ফলাফল_ <<> ছাড়াই বৈধ ডিফল্ট কনস্ট্রাক্টর যুক্তিগুলির উপর নির্ভর না করে কোনও টেমপ্লেট দ্বারা প্রকারটি ফেরত পাওয়া অবাস্তব।
— রবার্ট ম্যাসন

4
@ রবার্টমাসন: std::declvalউপরে বর্ণিত কোডের মতো এই যুক্তিগুলি পুনরুদ্ধার করা যেতে পারে । অবশ্যই, এটি
— কুরুচিপূর্ণ

4
@ ডেভিডরডগ্রিজেজ-ড্রিবিয়াস আপনার মন্তব্যে "(আছে" :(
— নবীন

4
আরেকটি নোট: result_ofএবং এর সহায়ক result_of_tধরণটি সি ++ 17 হিসাবে পূর্বের কিছু বিধিনিষেধকে হ্রাস করে invoke_resultএবং invoke_result_tঅবহিত করা হয়েছে। এগুলি en.cppreferences.com/w/cpp/tyype/result_of এর নীচে তালিকাভুক্ত করা হয়েছে ।
— সিগমা

11

আপনার যদি এমন কোনও ধরণের প্রয়োজন হয় যা কোনও ফাংশন কলের মতো std::result_ofনা হয় তবে কেবল প্রযোজ্য হবে না। decltype()আপনাকে যে কোনও অভিব্যক্তির ধরণ দিতে পারে।

যদি আমরা কোনও ফাংশন কল ( std::result_of_t<F(Args...)>এবং এর মধ্যে decltype(std::declval<F>()(std::declval<Args>()...)) রিটার্নের ধরণ নির্ধারণের বিভিন্ন উপায়ে কেবল নিজেদের মধ্যে সীমাবদ্ধ রাখি তবে তার মধ্যে পার্থক্য রয়েছে।

std::result_of<F(Args...) হিসাবে সংজ্ঞায়িত করা হয়:

যদি INVOKE (declval<Fn>(), declval<ArgTypes>()...)একটি অমূল্য অপারেন্ড (ক্লজ 5) হিসাবে বিবেচনা করা হয় তখন অভিব্যক্তিটি ভালভাবে গঠন করা হয়, সদস্য টাইপডিফ টাইপটির নামটি decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...)); অন্যথায় রাখবেন, সদস্যের কোনও প্রকার থাকবে না।

এর মধ্যে পার্থক্য result_of<F(Args..)>::typeএবং decltype(std::declval<F>()(std::declval<Args>()...)সব কিছু INVOKE। টাইপ করতে বেশ খানিকটা দীর্ঘ সময় ছাড়াও declval/ decltypeসরাসরি ব্যবহার করা কেবল তখনই বৈধ হয় যদি Fসরাসরি কলযোগ্য (কোনও ফাংশন অবজেক্টের ধরণ বা কোনও ফাংশন বা কোনও ফাংশন পয়েন্টার)। result_ofসদস্যদের ফাংশনগুলিতে পয়েন্টার এবং সদস্য ডেটারে পয়েন্টারগুলিকে সমর্থন করে।

প্রাথমিকভাবে, একটি SFINAE- বান্ধব এক্সপ্রেশন ব্যবহার declval/ decltypeগ্যারান্টিযুক্ত, যেখানে std::result_ofআপনাকে ছাড়ের ব্যর্থতার পরিবর্তে একটি হার্ড ত্রুটি দিতে পারে। এটি C ++ 14 এ সংশোধন করা হয়েছে: std::result_ofএখন SFINAE- বান্ধব হওয়া দরকার ( এই কাগজটির জন্য ধন্যবাদ )।

সুতরাং একটি উপযুক্ত সি ++ 14 সংকলক, std::result_of_t<F(Args...)>কঠোরভাবে উচ্চতর। এটা তোলে পরিষ্কার, খাটো, এবং সঠিকভাবে † সমর্থন আরো Fগুলি ‡ ।


† যদি না হয়, তবে আপনি এটি এমন একটি প্রসঙ্গে ব্যবহার করছেন যেখানে আপনি সদস্যদের পয়েন্টারগুলিকে মঞ্জুরি দিতে চান না, সুতরাং std::result_of_tএমন ক্ষেত্রে সাফল্য পাবেন যেখানে আপনি এটি ব্যর্থ হতে চাইতে পারেন।

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

template <class F, class R = result_of_t<F()>>
R call(F& f) { return f(); }

int answer() { return 42; }

call(answer); // nope

সঠিক ব্যবহারটি হত result_of_t<F&()>, তবে এটি এমন একটি বিবরণ যা আপনাকে মনে রাখতে হবে না decltype।


একটি অ-রেফারেন্স টাইপ Tএবং একটি ফাংশনের template<class F> result_of_t<F&&(T&&)> call(F&& f, T&& arg) { return std::forward<F>(f)(std::move(arg)); }জন্য, ব্যবহার কি result_of_tসঠিক?
— জিঝেং তাই

এছাড়াও, আমরা যে যুক্তিটি পাস করি তা fযদি const Tআমরা একটি হয় তবে কি আমাদের ব্যবহার করা উচিত result_of_t<F&&(const T&)>?
— জিঝেং তাই
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.