C ++ 11 में 'टाइपडेफ' और 'उपयोग' के बीच क्या अंतर है?


905

मुझे पता है कि C ++ 11 में अब हम s की usingतरह टाइप उपनाम लिखने के लिए उपयोग कर सकते हैं typedef:

typedef int MyInt;

है, जो मैं समझता हूं, उसके बराबर:

using MyInt = int;

और वह नया वाक्य-विन्यास " template typedef" को व्यक्त करने के तरीके के प्रयास से उभरा :

template< class T > using MyType = AnotherType< T, MyAllocatorType >;

लेकिन, पहले दो गैर-टेम्पलेट उदाहरणों के साथ, क्या मानक में कोई अन्य सूक्ष्म अंतर हैं? उदाहरण के लिए, typedef"कमजोर" तरीके से अलियासिंग करें। यह है कि यह एक नया प्रकार नहीं बनाता है, लेकिन केवल एक नया नाम (उन नामों के बीच रूपांतरण निहित हैं)।

क्या यह समान है usingया यह एक नया प्रकार उत्पन्न करता है? क्या कोई मतभेद हैं?


215
मैं व्यक्तिगत रूप से नए वाक्यविन्यास को प्राथमिकता देता हूं क्योंकि यह नियमित चर असाइनमेंट के समान है, पठनीयता में सुधार करता है। उदाहरण के लिए, क्या आप पसंद करते हैं typedef void (&MyFunc)(int,int);या using MyFunc = void(int,int);?
मैथ्यू एम।

13
मैं पूरी तरह से सहमत हूं, मैं अब केवल नए सिंटैक्स का उपयोग करता हूं। इसलिए मैं पूछ रहा था, यह सुनिश्चित करने के लिए कि वास्तव में कोई अंतर नहीं है।
Klaim

80
@MatthieuM। वे दो अलग-अलग btw हैं। यह होना चाहिए typedef void MyFunc(int,int);(जो वास्तव में बुरा नहीं दिखता है), याusing MyFunc = void(&)(int,int);
आर। मार्टिनो फर्नांडीस

5
@ R.MartinhoFernandes कारण है कि आप की जरूरत है (&) में using MyFunc = void(&)(int,int);? क्या इसका मतलब MyFuncकिसी फ़ंक्शन का संदर्भ है? क्या होगा यदि आप & को छोड़ दें ?
अमीर

7
हाँ, यह एक फ़ंक्शन संदर्भ है। इसके बराबर है typedef void (&MyFunc)(int,int);। यदि आप &इसे छोड़ दें तो यह बराबर हैtypedef void MyFunc(int,int);
आर। मार्टिनो फर्नांडिस

जवाबों:


584

वे मानक (जोर मेरा) (7.1.3.2) से समतुल्य हैं:

एक उपनाम-घोषणापत्र द्वारा एक टंकण-नाम भी पेश किया जा सकता है। उपयोग करने वाले कीवर्ड के बाद पहचानकर्ता एक टाइप-बीफ़-नाम बन जाता है और पहचान-पत्र के बाद वैकल्पिक विशेषता-विशेष-सीक उस टाइप-एफ़-नाम के साथ जुड़ जाता है। इसके समान शब्दार्थ है जैसे कि इसे टाइपडिफ विनिर्देशक द्वारा पेश किया गया था। विशेष रूप से, यह एक नए प्रकार को परिभाषित नहीं करता है और यह टाइप-आईडी में प्रकट नहीं होगा।


24
उत्तर से, usingकीवर्ड का सुपरसेट होना प्रतीत होता है typedef। फिर, typdefभविष्य में पदावनत किया जाएगा?
इमिलिंड

49
निस्तारण आवश्यक रूप से हटाने के इरादे का संकेत नहीं करता है - यह केवल एक और साधन को पसंद करने के लिए एक बहुत मजबूत सिफारिश के रूप में खड़ा है।
लौह तारणहार

18
लेकिन तब मुझे आश्चर्य होता है कि उन्होंने सिर्फ टाइपराइफ को टेम्पल क्यों नहीं होने दिया। मुझे याद है कि कहीं न कहीं उन्होंने पढ़ा है कि उन्होंने usingवाक्यविन्यास को ठीक-ठीक पेश किया है क्योंकि typedefशब्दार्थ टेम्पलेट के साथ अच्छी तरह से काम नहीं करता था। जो किसी भी तरह इस तथ्य का खंडन करता है कि usingवास्तव में एक ही शब्दार्थ है।
celtschk

12
@celtschk: प्रस्ताव में कारण के बारे में बात की गई है n1489। एक टेम्पलेट उपनाम अन्य प्रकार के लिए एक उपनाम नहीं है , लेकिन टेम्पलेट्स के समूह के लिए एक उपनाम है। typedefनए वाक्यविन्यास की आवश्यकता के बीच अंतर करने के लिए। इसके अलावा, ध्यान रखें कि ओपी का प्रश्न गैर-टेम्पलेट संस्करणों के बीच अंतर के बारे में है।
जेसी गुड

4
तो क्यों इस अतिरेक whas की शुरुआत की? एक ही उद्देश्य के लिए 2 वाक्यविन्यास। और मैं typdefकभी भी पदावनत नहीं होता।
बेनोइट

237

वे काफी हद तक एक ही हैं, सिवाय इसके कि:

उपनाम की घोषणा टेम्प्लेट के साथ संगत है, जबकि सी शैली टाइपडिफ नहीं है।


29
विशेष रूप से उत्तर की सादगी के शौकीन और टाइपसेट की उत्पत्ति को इंगित करते हैं।
g24l

1
@ g24l का मतलब है कि आप टाइप करें ... शायद
मार्क.2377

typedefअगर मैं पूछ सकता हूं कि C और C ++ में क्या अंतर है ?
मैकसिनेक्स

196

का उपयोग करते हुए वाक्य रचना एक फायदा जब टेम्पलेट्स के भीतर इस्तेमाल किया है। यदि आपको टाइप एब्सट्रैक्शन की आवश्यकता है, लेकिन भविष्य में निर्दिष्ट किए जाने के लिए टेम्प्लेट पैरामीटर रखने की भी आवश्यकता है। आपको कुछ इस तरह लिखना चाहिए।

template <typename T> struct whatever {};

template <typename T> struct rebind
{
  typedef whatever<T> type; // to make it possible to substitue the whatever in future.
};

rebind<int>::type variable;

template <typename U> struct bar { typename rebind<U>::type _var_member; }

लेकिन सिंटैक्स का उपयोग इस उपयोग के मामले को सरल करता है।

template <typename T> using my_type = whatever<T>;

my_type<int> variable;
template <typename U> struct baz { my_type<U> _var_member; }

35
मैंने पहले से ही इस सवाल में बताया। मेरा प्रश्न यह है कि क्या आप टेम्पलेट का उपयोग नहीं करते हैं तो क्या टाइम्डिफ के साथ कोई अंतर है। उदाहरण के लिए, जब आप 'फू फू {init_value};) का उपयोग करते हैं; 'फू फू (init_value)' के बजाय दोनों एक ही काम करने वाले हैं, लेकिन बिल्कुल एक जैसे नियमों का पालन न करें। इसलिए मैं सोच रहा था कि क्या उपयोग करने के साथ एक समान अंतर था / टाइपडिफ।
Klaim

24

वे अनिवार्य रूप से समान हैं, लेकिन usingप्रदान करता है alias templatesजो काफी उपयोगी है। एक अच्छा उदाहरण मुझे मिल सकता है:

namespace std {
 template<typename T> using add_const_t = typename add_const<T>::type;
}

इसलिए, हम std::add_const_t<T>इसके बजाय उपयोग कर सकते हैंtypename std::add_const<T>::type


जहाँ तक मुझे पता है, यह std नाम स्थान के अंदर कुछ भी जोड़ने के लिए अपरिभाषित व्यवहार है
someonewithpc

5
@someonewithpc मैं कुछ भी नहीं जोड़ रहा था, यह पहले से मौजूद है, मैं सिर्फ टाइपनेम के उपयोग का एक उदाहरण दिखा रहा था। कृपया en.cppreference.com/w/cpp/types/add_cv
Validus Oculus

9

मुझे पता है कि मूल पोस्टर का बहुत अच्छा जवाब है, लेकिन इस धागे पर ठोकर खाने वाले किसी भी व्यक्ति के लिए जैसे मेरे पास प्रस्ताव से एक महत्वपूर्ण नोट है जो मुझे लगता है कि यहां चर्चा के मूल्य में कुछ जोड़ता है, विशेष रूप से टिप्पणियों में चिंताओं के बारे में अगर typedefकीवर्ड है भविष्य में पदावनत के रूप में चिह्नित किया जा रहा है, या निरर्थक / पुराने होने के लिए हटा दिया गया है:

यह सुझाव दिया गया है कि (फिर से) कीवर्ड टाइप करने के लिए ... टेम्पलेट उपनामों का परिचय दें:

template<class T>
  typedef std::vector<T, MyAllocator<T> > Vec;

उस नोटेशन में एक प्रकार का उपनाम पेश करने के लिए पहले से ज्ञात कीवर्ड का उपयोग करने का लाभ है। हालाँकि, यह कई अव्यवस्थाओं को भी प्रदर्शित करता है [sic] जिसके बीच एक संदर्भ में टाइप-नाम के लिए एक उपनाम पेश करने के लिए ज्ञात कीवर्ड का उपयोग करने का भ्रम जहां उपनाम एक प्रकार को नामित नहीं करता है, लेकिन एक टेम्पलेट; Vecहै एक प्रकार के लिए एक उपनाम है, और एक typedef-नाम के लिए नहीं लिया जाना चाहिए। नाम Vecपरिवार का एक नाम है std::vector<•, MyAllocator<•> >- जहां बुलेट एक प्रकार के नाम के लिए एक प्लेसहोल्डर है। निश्चित रूप से हम "टाइपडेफ" वाक्यविन्यास का प्रस्ताव नहीं करते हैं। दूसरी ओर वाक्य

template<class T>
  using Vec = std::vector<T, MyAllocator<T> >;

पढ़ा जा सकता है / के रूप में व्याख्या की: अब से, मैं के Vec<T>लिए एक पर्याय के रूप में उपयोग करेंगेstd::vector<T, MyAllocator<T> > । उस पढ़ने के साथ, अलियासिंग का नया वाक्य-विन्यास यथोचित तार्किक लगता है।

मेरे लिए, यह typedefC ++ में कीवर्ड के लिए निरंतर समर्थन का तात्पर्य है क्योंकि यह अभी भी कोड को अधिक पठनीय और समझने योग्य बना सकता है

usingकीवर्ड को अपडेट करना विशेष रूप से टेम्प्लेट के लिए था, और (जैसा कि स्वीकृत उत्तर में बताया गया था) जब आप गैर-टेम्प्लेट के साथ काम कर रहे होते हैं usingऔर typedefयंत्रवत् समान होते हैं, तो पसंद पूरी तरह से प्रोग्रामर के लिए उपयुक्तता और इरादे के संचार के आधार पर होती है। ।


2

दोनों कीवर्ड समतुल्य हैं, लेकिन कुछ कैविटीज़ हैं। एक यह है कि के साथ एक फ़ंक्शन पॉइंटर घोषित करने की using T = int (*)(int, int);तुलना में स्पष्ट है typedef int (*T)(int, int);। दूसरा यह है कि टेम्पलेट अन्य नाम के साथ संभव नहीं है typedef। तीसरा यह है कि typedefसार्वजनिक एपीआई में सी एपीआई को उजागर करने की आवश्यकता होगी ।

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