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


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.