আপডেট: সি ++ 11 এ এর std::addressof
পরিবর্তে কেউ ব্যবহার করতে পারে boost::addressof
।
আসুন প্রথমে বুস্ট থেকে কোডটি অনুলিপি করুন, বিটের চারপাশে সংকলকটির কাজ বিয়োগ:
template<class T>
struct addr_impl_ref
{
T & v_;
inline addr_impl_ref( T & v ): v_( v ) {}
inline operator T& () const { return v_; }
private:
addr_impl_ref & operator=(const addr_impl_ref &);
};
template<class T>
struct addressof_impl
{
static inline T * f( T & v, long ) {
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
static inline T * f( T * v, int ) { return v; }
};
template<class T>
T * addressof( T & v ) {
return addressof_impl<T>::f( addr_impl_ref<T>( v ), 0 );
}
আমরা যদি কার্যটির কোনও রেফারেন্স পাস করি তবে কী হবে ?
দ্রষ্টব্য: addressof
ফাংশনটির জন্য পয়েন্টার সহ ব্যবহার করা যাবে না
সি ++ এ যদি void func();
ঘোষিত হয়, func
তবে কোনও ফাংশনটির কোনও প্রসঙ্গ যা কোনও যুক্তি না নিয়ে এবং কোনও ফলাফল না দিয়ে ফিরে আসে। কোনও ক্রিয়াকলাপের এই রেফারেন্সটিকে তুচ্ছভাবে পয়েন্টারে ফাংশনে রূপান্তর করা যায় - থেকে @Konstantin
: 13.3.3.2 অনুযায়ী উভয় T &
এবং T *
ফাংশনগুলির জন্য পৃথক পৃথক। প্রথমটি হ'ল একটি পরিচয় রূপান্তর এবং দ্বিতীয়টি হ'ল ফাংশন-টু-পয়েন্টার রূপান্তর উভয়ই "সঠিক মিল" র্যাঙ্ক (১৩.৩.৩.১.১ সারণী 9) পেয়েছেন।
ফাংশন রেফারেন্স মধ্য দিয়ে পাস addr_impl_ref
, এর পছন্দ জন্য জমিদার রেজোলিউশনের একটি দ্ব্যর্থতা আছে f
, যা মেকি যুক্তি ধন্যবাদ সমাধান করা হয় 0
, যা একটি হল int
প্রথম এবং উন্নীত করা যেতে পারে long
(সমাকলন রূপান্তর)।
এইভাবে আমরা কেবল পয়েন্টারটি ফিরিয়ে দিই।
যদি আমরা কোনও রূপান্তর অপারেটরের সাথে কোনও প্রকার পাস করি তবে কী হবে?
যদি রূপান্তর অপারেটর একটি ফল দেয় T*
তবে আমাদের একটি দ্বিধাগ্রস্ততা থাকে: f(T&,long)
দ্বিতীয় আর্গুমেন্টের জন্য ইন্টিগ্রাল প্রচার প্রয়োজন হয়, যখন f(T*,int)
রূপান্তর অপারেটরের জন্য প্রথম দিকে ডাকা হয় (@ লিটবকে ধন্যবাদ)
এটি যখন addr_impl_ref
হবে। দ্য সি ++ স্ট্যান্ডার্ড ম্যান্ডেট কিক করে একটি রূপান্তর ক্রম সর্বাধিক একটি ব্যবহারকারী-সংজ্ঞায়িত রূপান্তর এ থাকতে পারে। প্রকারটি মোড়ানো addr_impl_ref
এবং ইতিমধ্যে একটি রূপান্তর ক্রম ব্যবহার জোর করে, ধরণের যে কোনও রূপান্তর অপারেটরটি আমরা "অক্ষম" করি।
এইভাবে f(T&,long)
ওভারলোডটি নির্বাচিত হয় (এবং ইন্টিগ্রাল প্রচার সম্পাদিত হয়)।
অন্য কোন ধরণের ক্ষেত্রে কী ঘটে?
সুতরাং f(T&,long)
ওভারলোডটি নির্বাচিত হয়, কারণ সেখানে টাইপটি T*
প্যারামিটারের সাথে মেলে না ।
দ্রষ্টব্য: বোরল্যান্ডের সামঞ্জস্যতা সম্পর্কিত ফাইলের মন্তব্যগুলি থেকে, অ্যারেগুলি পয়েন্টারগুলিতে ক্ষয় হয় না, তবে রেফারেন্স দিয়ে পাস হয়।
এই ওভারলোডে কী ঘটে?
আমরা operator&
প্রকারটি প্রয়োগ করা এড়াতে চাই , কারণ এটি অতিরিক্ত লোড হয়েছে।
স্ট্যান্ডার্ড গ্যারান্টি দেয় যা reinterpret_cast
এই কাজের জন্য ব্যবহার করা যেতে পারে (@ মাত্তিও ইটালিয়া এর উত্তর: 5.2.10 / 10 দেখুন)
সংকলক সতর্কতাগুলি এড়ানোর জন্য বুস্ট কিছু যোগ্যতা const
এবং volatile
কোয়ালিফায়ার যুক্ত করেছে (এবং সঠিকভাবে const_cast
সেগুলি সরাতে একটি ব্যবহার করুন)।
- কাস্ট
T&
করার জন্যchar const volatile&
- স্ট্রিপ
const
এবংvolatile
&
ঠিকানা নিতে অপারেটর প্রয়োগ করুন
- ফিরে যাও ক
T*
const
/ volatile
সঙ্গীত এর কালো জাদু একটি বিট, কিন্তু এটা (বরং 4 overloads প্রদানের চেয়ে) কাজ সহজ করে দেয়। নোট যে যেহেতু T
অযোগ্য, যদি আমরা একটি পাস ghost const&
, তারপর T*
হয় ghost const*
এইভাবে কোয়ালিফায়ার সত্যিই হারিয়ে হয়নি।
সম্পাদনা: পয়েন্টার ওভারলোডটি পয়েন্টার ফাংশনগুলির জন্য ব্যবহৃত হয়, আমি উপরের ব্যাখ্যাটি কিছুটা সংশোধন করেছি। যদিও এখনও এটি প্রয়োজনীয় তা আমি এখনও বুঝতে পারি না ।
নীচের আইডিয়োন আউটপুটটি কিছুটা পরিমাণে এটির যোগফল ।