সর্বনিম্ন ব্যয়বহুল আর্গুমেন্টের ধরণ নির্ধারণ করার একটি সঙ্কলন সময় উপায়


15

আমার দেখতে এমন একটি টেম্পলেট রয়েছে

template <typename T> class Foo
{
public:
    Foo(const T& t) : _t(t) {}
private:
    const T _t;
};

যে ক্ষেত্রে আর্গুমেন্টের ধরনটি বুল বা চরের মতো তুচ্ছ, সেখানে কনস্ট্যান্ড রেফারেন্স ব্যবহার করা এড়াতে কি কোনও সচেতন টেমপ্লেট রূপক পদ্ধতি রয়েছে? মত:

Foo(stl::smarter_argument<T>::type t) : _t(t) {}

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

1
আমি নিখুঁত ফরোয়ার্ডিং সম্পর্কে আরও চিন্তিত হব তবে ছোট ডেটা ধরণের ক্ষেত্রে রেফারেন্স এড়ানো avo আমি অনুমান করছি যে r- মান রেফারেন্স দ্বারা পাস করা বেশিরভাগ ক্ষেত্রে পাস-বাই-ভ্যালুতে অনুকূলিত হতে পারে।
সুপার

কিছু মনে রাখতে হবে, উত্তরে নির্দেশিত নয়: আপনি যা করছেন তা অন্তর্নিহিত ছাড়ের গাইডগুলিকে পরাস্ত করবে। আপনার যদি ক্লাস টেম্পলেট আর্গুমেন্ট ছাড়ের জন্য কাজ করে তবে আপনি একটি সুস্পষ্ট ছাড়ের গাইড লিখতে ভুলবেন না Foo
ব্রায়ান

উত্তর:


13

আমি মনে করি সঠিক ধরণের বৈশিষ্ট্য is_scalar। এটি নিম্নলিখিত হিসাবে কাজ করবে:

template<class T, class = void>
struct smarter_argument{
    using type = const T&;
};

template<class T>
struct smarter_argument<T, std::enable_if_t<std::is_scalar_v<T>>> {
    using type = T;
};

সম্পাদনা:

উপরেরটি এখনও কিছুটা পুরাতন-স্কুল, এই আরও সংক্ষিপ্ত সংস্করণটি আমাকে স্মরণ করিয়ে দেওয়ার জন্য @ হোলিব্ল্যাকগ্যাটকে ধন্যবাদ:

template<class T>
using smarter_argument_t = std::conditional_t<std::is_scalar_v<T>, T, const T&>;

is_fundamentalকাজ করবে না ?
তারেক দাখরান

2
@ তারেকদখরান স্কেলারে পয়েন্টার এবং এনামগুলি অন্তর্ভুক্ত রয়েছে যা মৌলিক নয়, যা মান আইএমও দ্বারা পাস করা উচিত।
এলএফ

আমি ক্লাস = অকার্যকর সিনট্যাক্সের সাথে পরিচিত নই। এর অর্থ কি এটি কিছু হতে পারে কারণ এটি উপেক্ষা করা হয়েছে?
সিপ্পিগুই

1
= voidএর অর্থ এটির একটি ডিফল্ট প্রকার যা শূন্য, তাই ব্যবহার smarter_argument<T>করা আসলে smarter_argument<T, void>। এই তর্কটির জন্য আমি একটি নাম রেখেছি যেহেতু আমাদের এটির প্রয়োজন নেই, তাই class = voidকোনও নাম ছাড়াই। এটি গুরুত্বপূর্ণ যে std::enable_if_tক্ষেত্রে এটি সক্ষম হওয়া ক্ষেত্রে এটি ডিফল্ট টাইপের সাথে মিলে যাওয়ার জন্যও শূন্য থাকতে হবে।
n314159

2
সরলীকরণ করা যেতে পারে template <typename T> using smarter_argument = std::conditional_t<std::is_scalar_v<T>, T, const T &>;
হলিব্ল্যাকগ্যাট

3

আমি sizeof(size_t)(বা sizeof(ptrdiff_t)) যা আপনার মেশিনের সাথে সম্পর্কিত "আদর্শ" আকারটি প্রত্যাশার সাথে প্রত্যাশা করব যে এই আকারের যে কোনও ভেরিয়েবল একটি রেজিস্ট্রারের সাথে ফিট করে। সেক্ষেত্রে আপনি নিরাপদে এটি মান দ্বারা পাস করতে পারেন। তদুপরি, @ n314159 দ্বারা প্রস্তাবিত হিসাবে (এই পোস্টের শেষে মন্তব্যগুলি দেখুন) পরিবর্তনশীলটিও নিশ্চিত হয় তা নিশ্চিত করার জন্য এটি দরকারী trivialy_copyable

এখানে একটি সি ++ 17 ডেমো রয়েছে:

#include <array>
#include <ccomplex>
#include <iostream>
#include <type_traits>

template <typename T>
struct maybe_ref
{
  using type = std::conditional_t<sizeof(T) <= sizeof(size_t) and
                                  std::is_trivially_copyable_v<T>, T, const T&>;
};

template <typename T>
using maybe_ref_t = typename maybe_ref<T>::type;

template <typename T>
class Foo
{
 public:
  Foo(maybe_ref_t<T> t) : _t(t)
  {
    std::cout << "is reference ? " << std::boolalpha 
              << std::is_reference_v<decltype(t)> << std::endl;
  }

private:
  const T _t;
};

int main()
{
                                                          // with my machine
  Foo<std::array<double, 1>> a{std::array<double, 1>{}};  // <- by value
  Foo<std::array<double, 2>> b{std::array<double, 2>{}};  // <- by ref

  Foo<double>               c{double{}};                // <- by value
  Foo<std::complex<double>> d{std::complex<double>{}};  // <- by ref
}

মনে রাখবেন যে "আপনার মেশিনের পয়েন্টার আকার" এর মতো কোনও জিনিস নেই। উদাহরণস্বরূপ এটি চালান : struct Foo { void bar(){ }; int i; }; std::cout << sizeof(&Foo::i) << std::endl; //prints 8 std::cout << sizeof(&Foo::bar) << std::endl; //prints 16
ব্লুটিউন

@ ব্লুটিউন আকর্ষণীয়, মন্তব্যের জন্য ধন্যবাদ। আপনার উদাহরণ হিসাবে দেখায় স্ট্যাকওভারফ্লো.com/a/6751914/2001017 দেখুন : পয়েন্টার এবং ফাংশন পয়েন্টারগুলির বিভিন্ন আকার থাকতে পারে। এমনকি বিভিন্ন পয়েন্টারগুলির বিভিন্ন আকার থাকতে পারে। ধারণাটি ছিল মেশিনটির "সাধারণ" আকারের। আমি
আকার

1
@ পিকাড সম্ভবত আপনি তার <=পরিবর্তে ব্যবহার করতে চান ==, বেশিরভাগ মেশিনে আপনার বর্তমান কোডটি charউদাহরণ হিসাবে উদাহরণ হিসাবে গ্রহণ করে যদি আমি এটি সঠিক দেখি।
n314159

2
Tতুচ্ছ কপিযোগ্য হিসাবে আপনি যাচাই করতে পারেন । উদাহরণস্বরূপ একটি ভাগ করা পয়েন্টার size_tআমার প্লেটফর্মের আকারের দ্বিগুণ এবং এটি কেবলমাত্র একটি পয়েন্টার দিয়ে প্রয়োগ করা যেতে পারে, এটি একই আকারে নেমে। তবে আপনি অবশ্যই শেয়ারড_প্টরকে কনস্টের রেফ দ্বারা নিতে চান, মান দ্বারা নয়।
n314159

@ n314159 হ্যাঁ এটি একটি উন্নতি হবে। আমার উত্তরটিতে আপনার ধারণা অন্তর্ভুক্ত করা আপনি কি ঠিক আছেন?
পিকাউড ভিনসেন্ট

2

আমি সি ++ ২০ টি কীওয়ার্ড ব্যবহার করব requires। এমনি:

#include <iostream>

template<typename T>
class Foo
{
public:
    Foo(T t) requires std::is_scalar_v<T>: _t{t} { std::cout << "is scalar" <<std::endl; }
    Foo(const T& t) requires (not std::is_scalar_v<T>): _t{t} { std::cout << "is not scalar" <<std::endl;}
private:
    const T _t;
};

class cls {};

int main() 
{
    Foo{true};
    Foo{'d'};
    Foo{3.14159};
    cls c;
    Foo{c};

    return 0;
}

নিম্নলিখিত আউটপুটটি দেখতে আপনি অনলাইন কোড চালনা করতে পারেন:

is scalar
is scalar
is scalar
is not scalar

মজাদার. কনস্ট্রাক্টর আর্গুমেন্টের জন্য কনস্ট অটো এবং ব্যবহার করে কি কোনও সুবিধা রয়েছে?
সিপ্পিগুই

@ সিপিগুয়ে: আপনি এই প্রশ্নটি করতে পেরে আমি আনন্দিত। যদি আমি "কনস্ট টি অ্যান্ড টি" যুক্ত "কনট অটো & টি" যুক্তিটি প্রতিস্থাপন করি তবে কোডটি সংকলন করবে না। ত্রুটিটি "... 'ফু' এর টেমপ্লেট আর্গুমেন্টগুলির জন্য দ্ব্যর্থক ছাড় reads ... আপনি খুঁজে পেতে পারেন কেন?
ব্লুটিউন

1
@ সিপ্পিগুয়ে: আমাদের আলোচনার ফলে আমি উত্থাপিত একটি প্রশ্নের ফলস্বরূপ। আপনি এটি এখানে খুঁজে পেতে পারেন ।
ব্লুটিউন

1
ধারণাগুলি এখানে ওভারকিল এবং বিকল্পের তুলনায় যথেষ্ট শক্তিশালী read
এসএস অ্যান

1
@ এসএস অ্যান: আইএমএইচও সি ++ ২০ টি ধারণা ব্যবহার করে কখনই ওভারকিল হয় না। এটা ঠিক মার্জিত। আমি এখন পর্যন্ত যে বিকল্পগুলি দেখেছি সেগুলি IMHO পড়া আরও কঠিন, কারণ নেস্টেড টেম্পলেটগুলির ব্যবহার।
ব্লুটিউন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.