2016-07-24 21 views
19

मान लिया जाये कि हमखाका उर्फ ​​और विशेषज्ञता

template<typename T> 
struct Foo 
{ 
}; 

template<typename T> 
struct Bar 
{ 
}; 

template< template<typename T> class C > 
struct Pack 
{ 
    template<typename T> 
    using Container = C<T>; 
}; 

Foo और Pack<Foo>::Container अगर हम Foo के लिए एक विशेषज्ञता है एक ही बात के रूप में इलाज होना चाहिए रहे हैं? वह है:

template< template<typename T> class C > 
struct IsFoo : std::false_type 
{ 
}; 

template<> 
struct IsFoo<Foo> : std::true_type 
{ 
}; 

static_assert(IsFoo<Foo>::value,        "Only foos!"); 
static_assert(IsFoo< Pack<Foo>::Container >::value,   "Only foos!"); // ??? 
static_assert(IsFoo< Pack<Bar>::Container >::value == false, "Not a foo!"); 

क्या यह दूसरा दावा सही है? अपेक्षित व्यवहार क्या है? बिल्ली, क्या मैं भी वैध करने की कोशिश कर रहा हूं?

मैंने इसे तीन कंपाइलरों पर परीक्षण किया और मुझे अलग-अलग परिणाम मिल गए। ऐसा लगता है कि एमएसवीसी और सीएलएंग, Foo और Pack<Foo>::Container एक ही बात नहीं है, लेकिन GCC disagrees, जो ठंडा है, क्योंकि यह वही है जो मैं चाहता था।

तो, कौन सही है?

पीएस: मुझे यकीन नहीं है कि क्या मैं शीर्षक पर सही शब्दावली का उपयोग कर रहा हूं, न ही मेरे प्रश्न के शरीर के अंदर। सुझाव और सुधार स्वागत से अधिक हैं।

+0

मैंने सोचा था कि टेम्पलेट विशेषज्ञता प्रकार या मान के लिए है। यहां 'फू' एक टेम्पलेट है, न तो एक प्रकार और न ही कोई मान। प्रश्न के लिए +1। – zahir

+5

[सीडब्ल्यूजी 1286] (http://wg21.link/cwg1286)। – cpplearner

+0

आपके उदाहरण को संशोधित करना जैसे कि 'IsFoo' का टेम्पलेट पैरामीटर टेम्पलेट के बजाए एक टाइपनाम है, एमएसवीसी और जीसीसी दोनों के पास आपके मूल उदाहरण पर जीसीसी के समान उत्पादन होता है। (देखें: http://coliru.stacked-crooked.com/a/f3052a75286f82e2)। – jtedit

उत्तर

1

14.5.7 Alias templates

1 एक टेम्पलेट-घोषणा जिसमें घोषणा एक उपनाम-घोषणा (क्लॉज 7) है पहचानकर्ता वाणी एक उर्फ ​​टेम्पलेट किया जाना है। एक उपनाम टेम्पलेट प्रकार के परिवार के लिए एक नाम है। उपनाम टेम्पलेट का नाम टेम्पलेट-नाम है।

2 एक टेम्पलेट आईडी एक उपनाम टेम्पलेट की विशेषज्ञता को दर्शाता है, यह उर्फ ​​के प्रकार के आईडी में टेम्पलेट-पैरामीटर के लिए अपने टेम्पलेट तर्कों की प्रतिस्थापन द्वारा प्राप्त जुड़े प्रकार के बराबर है टेम्पलेट।

अपने उदाहरण Foo और Pack<Foo>::Container (कोई पैरामीटर सूची) में टेम्पलेट ऐसे नाम हैं जो एक प्रकार है, लेकिन केवल एक टेम्पलेट का प्रतिनिधित्व नहीं करते हैं। उदाहरण के लिए Foo<int> और Pack<Foo>::Container<int> टेम्पलेट-आईडी होंगे और इस प्रकार समकक्ष होंगे।

मेरे ज्ञान के लिए मानक टेम्पलेट-नामों के बीच कोई समकक्ष संबंध निर्दिष्ट नहीं करता है, इसलिए एमएसवीसी और क्लैंग यह मानने के लिए सही हैं कि केवल समान टेम्पलेट-नाम समकक्ष हैं।

लेकिन यदि आप अपने विशिष्ट उपयोग मामले के लिए पर्याप्त हैं तो आप अभी भी टेम्पलेट-आईडी के आधार पर विशेषज्ञ या अधिभार कर सकते हैं। उदा .:

template< typename C > 
struct IsFoo : std::false_type 
{ 
}; 

template<class T> 
struct IsFoo<Foo<T>> : std::true_type 
{ 
}; 

static_assert(IsFoo<Foo<int>>::value,        "Only foos!"); 
static_assert(IsFoo< Pack<Foo>::Container<int> >::value,   "Only foos!"); 
static_assert(IsFoo< Pack<Bar>::Container<int> >::value == false, "Not a foo!"); 

या

template<class T> 
void do_stuff(const T&) {} 

template<class T> 
void do_stuff(const Foo<T>&) {} 
संबंधित मुद्दे