টেমপ্লেটগুলিতে সঠিক ধরণের ডেটা কীভাবে ফিরবেন?


9
#include <iostream>
using namespace std;

template <class X, class Y>
Y big(X a, Y b)
{
   if (a > b)
      return (a);
   else return (b);
}

int main()
{
   cout << big(32.8, 9);
}

এখানে আমি সিপিপি টেমপ্লেট ব্যবহার করছি, তাই যখন আমি ফাংশন কল bigএর বাইপাস আর্গুমেন্ট doubleএবং intটাইপ, আমি ফিরতি জবাব যা চান double। এখানে টাইপ করুন, এটি 32পরিবর্তে ফিরে আসে 32.8

আমি কীভাবে আমার পছন্দসই আউটপুট পাব? কীভাবে সঠিক রিটার্ন টাইপ bigফাংশন লিখবেন ?


1
একটি ফাংশন কেবল একটি স্থির টাইপ দিতে পারে। কী টাইপ ফিরে আসবে আপনি রান-টাইমে চয়ন করতে পারবেন না।
জেস্পার জুহল

1
আপনি কীভাবে std::maxপ্রয়োগ করা হয় তা দেখতে চাইতে পারেন । ফাংশনটির রিটার্ন টাইপ অবশ্যই C ++ এ সংকলন সময়ে জানা উচিত। সুতরাং এই রিটার্নের ধরণটি আপনার পরামিতিগুলির রানটাইম মানের উপর নির্ভর করে না থাকতে পারে। এই কারণেই এই জাতীয় ক্রিয়াকলাপের জন্য আপনার একই ধরণের দুটি প্যারামিটারের প্রয়োজন (যেমন, টাইপ এক্স রয়েছে, তবে ওয়াই নয়)।
বরিস ডালস্টাইন

উত্তর:


12

একটি ফাংশনে কেবলমাত্র একটি রিটার্ন টাইপ থাকতে পারে যা সংকলন সময়ে জানা উচিত। যাইহোক, আপনি ব্যবহার করতে পারেন std::common_type, উভয় পরামিতি রূপান্তরিত হতে পারে যে টাইপ ফিরে।

হবে

#include <type_traits>
template <class X, class Y>
typename std::common_type<X,Y>::type big(X a, Y b)
{
   if (a > b)
      return a;
   else return b;
}

এবং এটি পরীক্ষা করতে পেরেছে যে এটি আসলে doubleকখন ফিরে আসে intএবং doubleআমরা কী করতে পারি:

int main() {
    auto x = big(4.2,42);
    std::cout << std::is_same<decltype(x),double>::value;
}

যা ছাপায়

1

পিএস: std::common_typeদৃশ্যের পিছনে টার্নারি অপারেটর ব্যবহার করতে পারে এবং যেমন এই সমাধান অন্যান্য উত্তরগুলি ( auto+ টের্নারি) থেকে আলাদা নয় । আসল শক্তি std::common_typeহ'ল এটি যে কোনও সংখ্যক পরামিতি গ্রহণ করে।


10

রিটার্নের ধরণটি সংকলন-সময়ে নির্ধারণ করতে হবে। আপনি শর্তসাপেক্ষ অপারেটরের সাথে ট্রেলিং রিটার্নটি ব্যবহার করতে পারেন , যদি আপনি এর মধ্যে সীমাবদ্ধ থাকেন ।

template <typename X, typename Y>
auto big(X&& a, Y&& b) -> decltype(a > b ? a : b) // ---> like this
{
   return  a > b ? a : b;
}

লাইভ দেখুন


তবে, আপনি যদি অ্যাক্সেস পেয়ে থাকেন বা উচ্চতর autoরিটার্ন যথেষ্ট হয়, কারণ আপনি যদি শর্তসাপেক্ষ অপারেটরের সাথে নিম্নরূপ ব্যবহার করেন তবে সংকলকটি সঠিক প্রকারটি কেটে যাবে:

template <typename X, typename Y>
auto big(X a, Y b)
{
   return  a > b ? a : b;
}

লাইভ দেখুন


কমপক্ষে সি ++ ১৪ এর মতো, ট্রেলিং রিটার্নের ধরণের দরকার নেই।
মধ্যাহ্নে

@ ওয়ালনাট শুভ পয়েন্ট আরও একটি বিকল্প ফরোয়ার্ডিং রেফারেন্স?
JeJo

1
@ জিজো হ্যাঁ, আমি অনুমান করি যে এটিও ঠিক আছে তবে সম্ভবত অর্থহীন, কারণ আপনি কোনও যুক্তিই সংশোধন করছেন না এবং রিটার্নের ধরণটি এখনও উভয় ক্ষেত্রেই মূল্যবান রেফারেন্স হতে পারে (যদিও সম্ভাব্য নয় const)।
আখরোট

আমি আমার মন্তব্যগুলি সরিয়ে দিয়েছি কারণ সেগুলি আর প্রয়োগ হয় না, তবে আমি উত্তরে একটি সতর্কতা যুক্ত করার পরামর্শ দেব যা আপনি প্যারামিটারগুলি বাই-ভ্যালু নিতে পারবেন না।
আখরোট

যদি আপনার কোড কেউ সৌন্দর্য, মনে হয় যে গৃহীত পরামিতি সিদ্ধান্ত নেবে যা রিটার্ন টাইপ কেউ যা পাবেন না মামলা! খ এর চেয়েও বড় হলেও আপনি সর্বদা দ্বিগুণ ফিরে আসবেন।
ক্লাউস

4

হিসাবে আপনার রিটার্ন টাইপ উপলক্ষে সালে Yএবং একটি ক্ষণস্থায়ী intআপনার দ্বিতীয় প্যারামিটার হিসাবে, আপনি পরিষ্কারভাবে চিহ্নিত করেছেন যে Yএকজন int। এখানে কোন বিস্ময় চলছে।

#include <iostream>

template <typename X, typename Y>
decltype(auto) big(const X& a, const Y& b)  // return type can just be auto as well 
{
    return a > b ? a : b;
}

int main()
{
    std::cout << big(32.8, 9) << '\n';
    std::cout << big(9, 32.8) << '\n';
    std::cout << big(32.8, 90) << '\n';
    std::cout << big(90, 32.8) << '\n';
}

এটি স্ক্রিনে চারটি সঠিক মান মুদ্রণ করে।

https://godbolt.org/z/fyGsmo

একটি বিষয় যা লক্ষ্য করা দরকার তা হ'ল এটি কেবল সেই ধরণের জন্য কাজ করবে যা একে অপরের সাথে তুলনা করা যায়, অর্থাত, সংকলক সুস্পষ্টভাবে তুলনার জন্য এক প্রকারকে অন্য প্রকারে রূপান্তরিত করবে।

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


@ ওয়ালনাট দুর্ঘটনাক্রমে কোনও রেফারেন্স ফিরিয়ে দেওয়া এই সাইটটি এটির চেয়ে বেশি শক্তিশালী। তবে অপরিবর্তিত আচরণ সম্পর্কে জেনে রাখা ভাল। এটি কোডের মতো নয় তবে আমি যেভাবেই লিখব; এটি একটি প্রশ্নের উত্তর।
মাঝামাঝি

1
আহ। আমি আপনার আগের মন্তব্যটি দুটি স্বতন্ত্র পয়েন্ট হিসাবে পড়েছি এবং প্রভাব এবং কারণ হিসাবে নয়। আমি উপযুক্ত সম্পাদনা করতে পারি can

আমি একটি অতিরিক্ত দাবি অস্বীকার করেছি।
16:56

2

আপনার যথাযথ পরিস্থিতির জন্য এটি সঠিক সমাধান নয়, সমস্ত সম্ভাবনার মধ্যেই - অন্যান্য উত্তরগুলি আপনি যা চান তার কাছাকাছি হতে পারে।

যাইহোক, যদি আপনি সত্যিই কিছু কারণে রানটাইম এ সম্পূর্ণরূপে বিভিন্ন ধরনের ফিরে যাওয়ার প্রয়োজন, সঠিক সমাধান (যেহেতু ) একটি ব্যবহার করা std::variantকোন ধরনের নিরাপদ ইউনিয়নের কেমন হয়।

#include <variant>

template <typename X, typename Y>
std::variant<X, Y> max(X a, Y b) {
  if (a > b)
    return std::variant<X, Y>(std::in_place_index_t<0>, a);
  else
    return std::variant<X, Y>(std::in_place_index_t<1>, b);
}

মনে রাখবেন যে প্রত্যাশিত মানটি সম্ভবত প্রত্যাশিত ব্যবহার std::visitবা এর মতো ব্যবহার করে ফিরে আসা মানটি মোকাবেলার জন্য কলারে রয়েছে ।


-2

এটি ইনট রিটার্ন করে কারণ ওয়াই একটি ইনট্রি এবং এটি এটি 32.8 কে কাস্ট করে। আপনি যখন বড় 32,82 ডেকেছিলেন এটি একটি ভাসা, তবে 8 টি একটি অন্তর্নিহিত এবং ফাংশন রিটার্নের ধরণটি হ'ল Y, যা অন্তর্নিহিত।

কোনটি বড় রিটার্ন টাইপ করে রানটাইমের সময় আপনার জানা দরকার তাই আপনি এটি ঠিক করতে পারবেন না, সুতরাং এ এবং বি একই ধরণের তৈরি করুন:

    #include <iostream>
    using namespace std;

    template <typename X>

    X big (X a, X b)
    {
    if (a>b)
    return a;

    else return b;
    }

    int main()
    {
    cout<< big (32.8, 9.0);
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.