C ++ 11 में, using
जब कीवर्ड का उपयोग किया जाता है तो type alias
वह समान होता है typedef
।
7.1.3.2
एक उपनाम-घोषणापत्र द्वारा एक टंकण-नाम भी पेश किया जा सकता है। उपयोग करने वाले कीवर्ड के बाद पहचानकर्ता एक टाइप-बीफ़-नाम बन जाता है और पहचान-पत्र के बाद वैकल्पिक विशेषता-विशेष-सीक उस टाइप-एफ़-नाम के साथ जुड़ जाता है। इसके समान शब्दार्थ है जैसे कि इसे टाइपडिफ विनिर्देशक द्वारा पेश किया गया था। विशेष रूप से, यह एक नए प्रकार को परिभाषित नहीं करता है और यह टाइप-आईडी में प्रकट नहीं होगा।
Bjarne Stroustrup एक व्यावहारिक उदाहरण प्रदान करता है:
typedef void (*PFD)(double); // C style typedef to make `PFD` a pointer to a function returning void and accepting double
using PF = void (*)(double); // `using`-based equivalent of the typedef above
using P = [](double)->void; // using plus suffix return type, syntax error
using P = auto(double)->void // Fixed thanks to DyP
प्री-सी ++ 11, using
कीवर्ड सदस्य कार्यों को दायरे में ला सकता है। C ++ 11 में, अब आप कंस्ट्रक्टरों के लिए ऐसा कर सकते हैं (एक और ब्रेज़ेन स्ट्रॉस्ट्रुप उदाहरण):
class Derived : public Base {
public:
using Base::f; // lift Base's f into Derived's scope -- works in C++98
void f(char); // provide a new f
void f(int); // prefer this f to Base::f(int)
using Base::Base; // lift Base constructors Derived's scope -- C++11 only
Derived(char); // provide a new constructor
Derived(int); // prefer this constructor to Base::Base(int)
// ...
};
एक नए कीवर्ड या नए सिंटैक्स को पेश न करने के औचित्य के पीछे बेन वोइट एक बहुत अच्छा कारण प्रदान करता है। मानक जितना संभव हो उतना पुराने कोड को तोड़ने से बचना चाहता है। यही कारण है कि प्रस्ताव दस्तावेजों में आप वर्गों की तरह देखेंगे Impact on the Standard
, Design decisions
और वे बड़े कोड कैसे प्रभावित कर सकते। ऐसी स्थितियाँ होती हैं जब कोई प्रस्ताव वास्तव में एक अच्छा विचार लगता है, लेकिन उसमें कर्षण नहीं हो सकता है क्योंकि इसे लागू करना बहुत मुश्किल होगा, बहुत भ्रामक होगा, या पुराने कोड का खंडन करेगा।
यहां 2003 n1449 से एक पुराना पेपर है । औचित्य टेम्प्लेट से संबंधित प्रतीत होता है। चेतावनी: पीडीएफ से कॉपी करने के कारण टाइपो हो सकता है।
पहले एक खिलौना उदाहरण पर विचार करें:
template <typename T>
class MyAlloc {/*...*/};
template <typename T, class A>
class MyVector {/*...*/};
template <typename T>
struct Vec {
typedef MyVector<T, MyAlloc<T> > type;
};
Vec<int>::type p; // sample usage
इस मुहावरे के साथ मूलभूत समस्या, और इस प्रस्ताव के लिए मुख्य प्रेरक तथ्य यह है कि मुहावरा टेम्पलेट के मापदंडों को गैर-साक्ष्य संदर्भ में प्रकट करने का कारण बनता है। यही है, टेम्पलेट तर्कों को स्पष्ट रूप से निर्दिष्ट किए बिना फ़ंक्शन फू को नीचे कॉल करना संभव नहीं होगा।
template <typename T> void foo (Vec<T>::type&);
तो, वाक्य रचना कुछ बदसूरत है। हम बजाय नेस्टेड से बचना ::type
चाहते हैं हम निम्नलिखित की तरह कुछ पसंद करेंगे:
template <typename T>
using Vec = MyVector<T, MyAlloc<T> >; //defined in section 2 below
Vec<int> p; // sample usage
ध्यान दें कि हम विशेष रूप से शब्द "टाइपडेफ टेम्पलेट" से बचते हैं और भ्रम से बचने में मदद करने के लिए जोड़ी "का उपयोग" और "=" शामिल नए सिंटैक्स को बढ़ाते हैं: हम यहां किसी भी प्रकार को परिभाषित नहीं कर रहे हैं, हम इसके लिए एक पर्यायवाची (यानी) पेश कर रहे हैं। टेम्पलेट मापदंडों को शामिल करते हुए टाइप-आईडी (यानी प्रकार की अभिव्यक्ति) का एक अमूर्तन। यदि टेम्पलेट पैरामीटर का उपयोग प्रकार की अभिव्यक्ति में कटौती करने योग्य संदर्भों में किया जाता है, तो जब भी टेम्पलेट-आईडी बनाने के लिए टेम्पलेट उपनाम का उपयोग किया जाता है, तो संबंधित टेम्पलेट मापदंडों के मूल्यों को घटाया जा सकता है - इस पर और अधिक का पालन करेंगे। किसी भी स्थिति में, यह संभव है कि जेनेरिक कार्यों को लिखा जाए, जो Vec<T>
कि समर्पण के संदर्भ में काम करते हैं , और वाक्यविन्यास में भी सुधार होता है। उदाहरण के लिए हम फू को फिर से लिख सकते हैं:
template <typename T> void foo (Vec<T>&);
हम यहाँ रेखांकित करते हैं कि टेम्पलेट अलायस के प्रस्ताव के प्राथमिक कारणों में से एक यह था कि तर्क में कटौती और foo(p)
सफल होने के लिए कॉल ।
अनुवर्ती कागज n1489 बताता है कि using
उपयोग करने के बजाय क्यों typedef
:
यह सुझाव दिया गया है कि (टाइप करें) कीवर्ड टाइप का उपयोग करें - जैसा कि पेपर में किया गया है [4] - टेम्पलेट एलियास को पेश करने के लिए:
template<class T>
typedef std::vector<T, MyAllocator<T> > Vec;
उस नोटेशन में एक प्रकार का उपनाम पेश करने के लिए पहले से ज्ञात कीवर्ड का उपयोग करने का लाभ है। हालाँकि, यह कई असमानताओं को भी प्रदर्शित करता है जिनके बीच एक संदर्भ में टाइप-नाम के लिए उपनाम का परिचय देने के लिए ज्ञात कीवर्ड का उपयोग करने का भ्रम है जहां उपनाम किसी प्रकार को नामित नहीं करता है, लेकिन एक टेम्पलेट; Vec
एक प्रकार के लिए एक उपनाम नहीं है, और एक टाइप-बीफ़-नाम के लिए नहीं लिया जाना चाहिए। नाम Vec
परिवार का एक नाम है std::vector< [bullet] , MyAllocator< [bullet] > >
- जहां एक प्रकार के नाम के लिए बुलेट एक प्लेसहोल्डर है। नतीजतन हम "टाइपडेफ़" वाक्य रचना का प्रस्ताव नहीं करते हैं। दूसरी ओर सजा
template<class T>
using Vec = std::vector<T, MyAllocator<T> >;
पढ़ा जा सकता है / के रूप में व्याख्या की: अब से, मैं के Vec<T>
लिए एक पर्याय के रूप में उपयोग करेंगे std::vector<T, MyAllocator<T> >
। उस पढ़ने के साथ, अलियासिंग का नया वाक्य-विन्यास यथोचित तार्किक लगता है।
मुझे लगता है कि महत्वपूर्ण अंतर यहां बनाया गया है, टाइप एस के बजाय उर्फ तों । उसी दस्तावेज़ से एक और उद्धरण:
एक उपनाम-घोषणा एक घोषणा है, और परिभाषा नहीं है। एक उपनाम- घोषणापत्र एक घोषणा क्षेत्र में एक नाम को घोषणा के दाईं ओर से नामित प्रकार के लिए एक उपनाम के रूप में पेश करता है। इस प्रस्ताव का मूल नाम उपनामों के साथ खुद को चिंतित करता है, लेकिन स्पष्ट रूप से नामकरण-अलियासिंग या ओवरलोड कार्यों के नामकरण सेट के वैकल्पिक वर्तनी प्रदान करने के लिए संकेतन को सामान्यीकृत किया जा सकता है (आगे की चर्चा के लिए for 2.3 देखें)। [ मेरा ध्यान दें: उस अनुभाग में चर्चा की गई है कि क्या वाक्यविन्यास ऐसा लग सकता है और कारणों से यह प्रस्ताव का हिस्सा नहीं है। ] यह ध्यान दिया जा सकता है कि व्याकरण उत्पादन अलियास-घोषणा कहीं भी स्वीकार्य है एक टाइपराइफ घोषणा या नाम स्थान-अलियास-परिभाषा स्वीकार्य है।
सारांश, की भूमिका के लिए using
:
- टेम्प्लेट एलियासेस (या टेम्प्लेट टाइप्स, पूर्व पसंद किया जाता है)
- नाम स्थान उपनाम (यानी,
namespace PO = boost::program_options
और using PO = ...
समतुल्य)
- दस्तावेज़ कहता है
A typedef declaration can be viewed as a special case of non-template alias-declaration
। यह एक सौंदर्य परिवर्तन है, और इस मामले में समान माना जाता है।
- कुछ को दायरे में लाना (उदाहरण के लिए,
namespace std
वैश्विक दायरे में), सदस्य कार्य, निर्माणकर्ता को विरासत में देना
इसका उपयोग इसके लिए नहीं किया जा सकता है:
int i;
using r = i; // compile-error
इसके बजाय करें:
using r = decltype(i);
ओवरलोड का एक नामकरण।
// bring cos into scope
using std::cos;
// invalid syntax
using std::cos(double);
// not allowed, instead use Bjarne Stroustrup function pointer alias example
using test = std::cos(double);