निम्नलिखित मामले में आश्रित प्रकारों के लिए टाइपनेम का उपयोग करने की आवश्यकता क्यों नहीं है?


10

मैं, एक प्रकार का संदर्भ हटाने के बारे में पढ रहा हूं यहां

यह निम्नलिखित उदाहरण देता है:

#include <iostream> // std::cout
#include <type_traits> // std::is_same

template<class T1, class T2>
void print_is_same() {
  std::cout << std::is_same<T1, T2>() << '\n';
}

int main() {
  std::cout << std::boolalpha;

  print_is_same<int, int>();
  print_is_same<int, int &>();
  print_is_same<int, int &&>();

  print_is_same<int, std::remove_reference<int>::type>(); // Why not typename std::remove_reference<int>::type ?
  print_is_same<int, std::remove_reference<int &>::type>();// Why not typename std::remove_reference<int &>::type ?
  print_is_same<int, std::remove_reference<int &&>::type>();// Why not typename std::remove_reference<int &&>::type ?
}

typeमें रों std::remove_referenceलक्षण निर्भर प्रकार हैं।

संभव कार्यान्वयन

template< class T > struct remove_reference      {typedef T type;};
template< class T > struct remove_reference<T&>  {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};

लेकिन इसका उपयोग क्यों नहीं होता है typename std::remove_reference</*TYPE*/>::type?

जवाबों:


22

typeमें रों std::remove_referenceलक्षण निर्भर प्रकार हैं।

नहीं, वे यहां निर्भर नाम नहीं हैं। टेम्पलेट तर्क स्पष्ट रूप से निर्दिष्ट किए गए हैं int, int&और int&&। इसलिए, इस बिंदु पर प्रकार ज्ञात हैं।

दूसरी ओर, यदि आप std::remove_referenceटेम्पलेट पैरामीटर के साथ उपयोग करते हैं, जैसे

template <typename T>
void foo() {
    print_is_same<int, typename std::remove_reference<T>::type>();
}

तब आपको यह typenameबताने के लिए उपयोग करना होगा कि std::remove_reference<T>::typeयह एक प्रकार है जैसा कि आपकी अभिव्यक्ति अब टेम्पलेट पैरामीटर पर निर्भर करती है T


5

संक्षेप में, आपको typenameसंकलक को सुनिश्चित करने की आवश्यकता है कि

std::remove_reference<int>::type

वास्तव में एक प्रकार है। कुछ अन्य टेम्पलेट पर विचार करें

template <typename T>
struct foo {
    using type = int;
};

यहाँ foo::typeएक प्रकार है। लेकिन क्या होगा अगर कोई लाइन की विशेषज्ञता के साथ आपूर्ति करता है

template <> struct foo<int> {
    int type;
};

अब typeएक प्रकार नहीं है, लेकिन एक int। अब जब आप टेम्पलेट के अंदर फू का उपयोग करते हैं:

template <typanem T> 
struct bar {
    using type = typename foo<T>::type;
};

आपको संकलक को यह सुनिश्चित करना होगा कि foo<T>::typeवास्तव में एक प्रकार है, न कि कुछ और, क्योंकि केवल bar(और प्राथमिक टेम्पलेट foo) को देखकर कंपाइलर ऐसा नहीं कर सकता है।

हालाँकि, आपके mainमें std::remove_reference<int>::typeकोई टेम्पलेट पैरामीटर पर निर्भर नहीं करता है, इसलिए कंपाइलर आसानी से जांच सकता है कि क्या यह एक प्रकार है।


0

स्रोत को कंपाइलर पार्स करने में मदद करने के लिए कीवर्ड टाइपनेम का उपयोग किया जाता है। यह इंगित करता है कि आईडी एक प्रकार का नाम है, न कि एक चर नाम या विधि का नाम। लेकिन ऊपर संकलक जैसी स्थितियों में यह स्वयं पता लगा सकता है, इसलिए इस कीवर्ड की आवश्यकता नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.