সি ++ নালপ্ট্রার বাস্তবায়ন কীভাবে কাজ করে?


13

আমি কীভাবে nullptrকাজ করে তা জানতে আগ্রহী । N4659 এবং N4849 স্ট্যান্ডার্ডগুলি বলে:

  1. এটি টাইপ করতে হবে std::nullptr_t;
  2. আপনি এর ঠিকানা নিতে পারবেন না;
  3. এটি সরাসরি পয়েন্টার এবং পয়েন্টারে সদস্যতে রূপান্তরিত হতে পারে;
  4. sizeof(std::nullptr_t) == sizeof(void*);
  5. এর রূপান্তর boolহয় false;
  6. এর মানটি অবিচ্ছেদ্য ধরণের রূপে রূপান্তরিত হতে পারে (void*)0তবে পিছনে নয়;

সুতরাং এটি মূলত একই ধরণের অর্থ সহ ধ্রুবক (void*)0তবে এটির একটি আলাদা ধরণ রয়েছে। আমি std::nullptr_tআমার ডিভাইসে বাস্তবায়ন পেয়েছি এবং এটি নীচে রয়েছে।

#ifdef _LIBCPP_HAS_NO_NULLPTR

_LIBCPP_BEGIN_NAMESPACE_STD

struct _LIBCPP_TEMPLATE_VIS nullptr_t
{
    void* __lx;

    struct __nat {int __for_bool_;};

    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}

    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}

    template <class _Tp>
        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
        operator _Tp* () const {return 0;}

    template <class _Tp, class _Up>
        _LIBCPP_INLINE_VISIBILITY
        operator _Tp _Up::* () const {return 0;}

    friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;}
    friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;}
};

inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);}

#define nullptr _VSTD::__get_nullptr_t()

_LIBCPP_END_NAMESPACE_STD

#else  // _LIBCPP_HAS_NO_NULLPTR

namespace std
{
    typedef decltype(nullptr) nullptr_t;
}

#endif  // _LIBCPP_HAS_NO_NULLPTR

যদিও আমি প্রথম অংশে আরও আগ্রহী। এটি 1-5 পয়েন্টগুলি সন্তুষ্ট বলে মনে হচ্ছে, তবে কেন এটির একটি সাবক্লাস __nat এবং এর সাথে সম্পর্কিত সমস্ত কিছুই আমার জানা নেই। আমি এটিও জানতে চাই কেন এটি অবিচ্ছেদ্য রূপান্তরগুলিতে ব্যর্থ হয়।

struct nullptr_t2{
    void* __lx;
    struct __nat {int __for_bool_;};
     constexpr nullptr_t2() : __lx(0) {}
     constexpr nullptr_t2(int __nat::*) : __lx(0) {}
     constexpr operator int __nat::*() const {return 0;}
    template <class _Tp>
         constexpr
        operator _Tp* () const {return 0;}
    template <class _Tp, class _Up>
        operator _Tp _Up::* () const {return 0;}
    friend  constexpr bool operator==(nullptr_t2, nullptr_t2) {return true;}
    friend  constexpr bool operator!=(nullptr_t2, nullptr_t2) {return false;}
};
inline constexpr nullptr_t2 __get_nullptr_t2() {return nullptr_t2(0);}
#define nullptr2 __get_nullptr_t2()

int main(){
    long l  = reinterpret_cast<long>(nullptr);
    long l2 = reinterpret_cast<long>(nullptr2); // error: invalid type conversion
    bool b  = nullptr; // warning: implicit conversion
                       // edditor error: a value of type "std::nullptr_t" cannot be used to initialize an entity of type "bool"
    bool b2 = nullptr2;
    if (nullptr){}; // warning: implicit conversion
    if (nullptr2){};
};

2
nullptr_tএকটি মৌলিক ধরনের। কীভাবে intবাস্তবায়ন হয়?
এলএফ

9
নোট #ifdef _LIBCPP_HAS_NO_NULLPTR। সংকলকটি যখন সরবরাহ করে না তখন এটি সর্বোত্তম-প্রচেষ্টা মতো মনে হয় nullptr
খ্রিস্ট

5
@ ফুলফুঙ্গো স্ট্যান্ডার্ডটি বলে যে nullptr_tএটি একটি মৌলিক প্রকার। এটিকে শ্রেণীর ধরণের হিসাবে প্রয়োগ করা কার্যকরভাবে বাস্তবায়ন করে না। খ্রিস্টের মন্তব্য দেখুন।
এলএফ

1
@ এলএফ স্ট্যান্ডার্ডের কি প্রযুক্তিগতভাবে কোনও মৌলিক ধরণের কোনও শ্রেণির ধরণের নয় তা প্রয়োজন?
এরেরিকা

উত্তর:


20

নাল্পটার কীভাবে কাজ করে তা জানতে আগ্রহী।

এটি সহজতম পদ্ধতিতে কাজ করে: ফিয়াট দ্বারা । এটি কাজ করে কারণ সি ++ স্ট্যান্ডার্ড বলে যে এটি কাজ করে এবং এটি সেইভাবে কাজ করে কারণ সি ++ স্ট্যান্ডার্ড বলে যে বাস্তবায়নগুলি অবশ্যই এটিকে সেই ফ্যাশনে কাজ করতে বাধ্য করে

এটি সনাক্ত করা গুরুত্বপূর্ণ যে সি ++ ভাষার নিয়ম ব্যবহার করে এটি প্রয়োগ করা অসম্ভবstd::nullptr_t । কোনও নাল পয়েন্টার ধ্রুবক থেকে ধরণের ধরণের std::nullptr_tপয়েন্টারে রূপান্তরটি কোনও ব্যবহারকারী-সংজ্ঞায়িত রূপান্তর নয়। এর অর্থ হল যে আপনি একটি নাল পয়েন্টার থেকে ধীরে ধীরে একটি পয়েন্টারে যেতে পারেন, তারপরে একটি ব্যবহারকারী-সংজ্ঞায়িত রূপান্তরটির মাধ্যমে অন্য কোনও ধরণের রূপান্তর করতে পারেন, সবগুলিই একক অন্তর্নিহিত রূপান্তর ক্রমে।

আপনি যদি nullptr_tশ্রেণি হিসাবে প্রয়োগ করেন তবে তা সম্ভব নয় । রূপান্তর অপারেটরগুলি ব্যবহারকারী-সংজ্ঞায়িত রূপান্তরগুলি উপস্থাপন করে এবং সি ++ এর অন্তর্নিহিত রূপান্তর সিকোয়েন্স বিধিগুলি এই জাতীয় অনুক্রমের জন্য একাধিক ব্যবহারকারী-সংজ্ঞায়িত রূপান্তরকে মঞ্জুরি দেয় না।

সুতরাং আপনার পোস্ট করা কোডটি একটি দুর্দান্ত অনুমান std::nullptr_t, তবে এটি এর চেয়ে বেশি কিছু নয়। এটি ধরণের বৈধ বাস্তবায়ন নয়। এটি সম্ভবত সংকলকটির পুরানো সংস্করণ থেকে (পিছনের দিকে সামঞ্জস্যের কারণে ছেড়ে দেওয়া হয়েছে) কম্পাইলারটির জন্য যথাযথ সমর্থন সরবরাহ করার আগে std::nullptr_t। আপনি যে এটি দ্বারা এটি দেখতে পারেন #defineগুলি nullptr, যখন সি ++ 11 বলছেন যে nullptrএকটি হল শব্দ , না একটি ম্যাক্রো।

সি ++ বাস্তবায়ন করতে পারে না std::nullptr_t, যেমন সি ++ প্রয়োগ করতে পারে না intবা করতে পারে না void*। কেবল বাস্তবায়নই সেগুলি বাস্তবায়ন করতে পারে। এটিকেই এটি "মৌলিক ধরণের" করে তোলে; এটি ভাষার একটি অংশ ।


এর মানটি অবিচ্ছেদ্য প্রকারে অভিন্নভাবে (অকার্যকর *) 0 তে রূপান্তরিত হতে পারে তবে পিছনের দিকে নয়;

নেই কোন অন্তর্নিহিত রূপান্তর অবিচ্ছেদ্য ধরনের একটি নাল পয়েন্টার ধ্রুবক থেকে। 0একটি অবিচ্ছেদ্য টাইপ থেকে রূপান্তর আছে , কিন্তু এটি কারণ এটি পূর্ণসংখ্যার আক্ষরিক শূন্য, যা ... একটি পূর্ণসংখ্যা।

nullptr_tএকটি পূর্ণসংখ্যার ধরণের (মাধ্যমে ) কাস্ট করা যেতে পারে reinterpret_castতবে এটি কেবল স্পষ্টতই পয়েন্টার এবং এ রূপান্তর করতে পারে bool



"C ++ ভাষার নিয়ম ব্যবহার করে std :: nullptr_t প্রয়োগ করা অসম্ভব" এর অর্থ কী? এর অর্থ কি সি ++ সংকলক পুরোপুরি সি ++ এ লেখা যাবে না (আমি অনুমান করছি না)?
উত্তর পূর্ব

3
@ উত্তরার্নার: আমি বোঝাতে চাইছি যে আপনি এমন ধরনের লিখতে পারবেন না যা প্রয়োজনীয় আচরণের সাথে সমান std::nullptr_t। ঠিক তেমন কোনও ধরনের আপনি লিখতে পারবেন না যা প্রয়োজনীয় আচরণের সাথে সমান int। আপনি কাছাকাছি যেতে পারেন, তবে এখনও উল্লেখযোগ্য পার্থক্য থাকবে। এবং আমি এর মতো বৈশিষ্ট্য সনাক্তকারী সম্পর্কে কথা বলছি না is_classতা প্রকাশ করুন যে আপনার ধরণটি ব্যবহারকারী-সংজ্ঞায়িত। মৌলিক ধরণের প্রয়োজনীয় আচরণ সম্পর্কে এমন কিছু বিষয় রয়েছে যা আপনি কেবল ভাষার নিয়ম ব্যবহার করে অনুলিপি করতে পারবেন না।
নিকল বোলাস

1
শুধু একটি শব্দ বাকী। আপনি যখন বলেন "সি ++ প্রয়োগ করতে পারে না nullptr_t" আপনি খুব বিস্তৃতভাবে কথা বলেন। এবং "কেবল বাস্তবায়নই এটি বাস্তবায়ন করতে পারে" বলা কেবল বিষয়গুলিকে বিভ্রান্ত করে। আপনি যা বলতে চাইছেন তা হ'ল nullptr_t" সি ++ পাঠাগারটিতে এটি প্রয়োগ করা যাবে না কারণ এটি বেস ভাষার একটি অংশ
স্পেনসার

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