2016-03-29 6 views
8

निम्नलिखित कोड:जीसीसी बनाम variadic तर्क के साथ साथ एक ही प्रकार के अतिरिक्त तर्क के साथ आंशिक विशेषज्ञता पर बजना व्यवहार

#include <cstddef> 

template <size_t N, 
      typename T, 
      T first, 
      T... rest> 
struct A { 
}; 

template<typename T, 
     T... args> 
struct A<0, T, args...> { 
}; 

int main() { 
    A<0, int, 1> a0; 
    A<2, int, 1, 2> a2; 
    return 0; 
} 

... g++ (संस्करण 5.1.0 और 5.3.0) के साथ संकलन नहीं है की वजह से:

error: partial specialization is not more specialized than the primary template because it replaces multiple parameters with a pack expansion

... लेकिन clang के साथ संकलित करता है।

क्या इस तरह के आंशिक विशेषज्ञता घोषित करने की अनुमति है?

साइड नोट: असल में, विशेषज्ञता A<0, int> दोनों खतरनाक है क्योंकि संकलक (टेम्पलेट तर्कों की गलत संख्या) के साथ संकलन करने में विफल रहता है।

+0

अनुमति देने के लिए 'एक <0, int>', आपको पहले टेम्पलेट बदलना होगा। विशेषज्ञता के लिए बहुत देर हो चुकी है। – Jarod42

+0

@ जारोड 42 हां मुझे पता है कि टेम्पलेट का इस तरह का तात्कालिकता गलत है, मैं आंशिक विशेषज्ञता के बारे में पूछ रहा हूं, केवल 'टी' के साथ आंशिक विशेषज्ञता के बारे में पूछ रहा हूं, 'जी ++' में त्रुटि बढ़ाना, लेकिन 'क्लैंग' नहीं करना (प्रश्न बनाने के लिए फिर से व्यवस्थित करना यह स्पष्ट है)। – Holt

+2

जीसीसी सही है। यह प्रति बीआर 14 9 5] (http://wg21.link/cwg1495) (कुछ हद तक असंतोषजनक है, क्योंकि यह जीसीसी के रखरखाव द्वारा रिपोर्ट किया गया था) का खराब गठबंधन है। –

उत्तर

8

जीसीसी सही है, कोड खराब है क्योंकि विशेषज्ञता वास्तव में अधिक विशिष्ट नहीं है।


नियम, [temp.class.spec] है से (लिंक के लिए की DR 1495, ज/टी टीसी परिणामस्वरूप):

Within the argument list of a class template partial specialization, the following restrictions apply: [...] The specialization shall be more specialized than the primary template (14.5.5.2).

आदेश है कि निर्धारित करने के लिए, हम करेंगे पुनर्लेखन संश्लेषित समारोह टेम्पलेट्स के रूप में दो:

template <size_t N, class T, T first, T... rest> 
void __f(A<N, T, first, rest...>); // primary 

template <class T, T... args> 
void __f(A<0, T, args...>);   // specialization 

और उसके बाद आंशिक आदेश नियमों के माध्यम से जाना। बदले में, प्रत्येक टेम्पलेट पैरामीटर के लिए नए प्रकार/मानों को संश्लेषित करना और यह देखना कि कटौती किसी भी दिशा में सफल हो सकती है।

निश्चित रूप से, विशेषज्ञता की कटौती प्राथमिक के साथ विफल होती है (N बनाम 0)। दूसरी दिशा में, [temp.deduct.partial] से:

If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails.

हम एक पैकेट के खिलाफ T first अनुमान की कोशिश कर रहे के बाद से, कटौती के रूप में अच्छी तरह से इस दिशा में विफल रहता है। इसका मतलब है कि संश्लेषित फ़ंक्शन टेम्पलेट्स में से कोई भी अन्य की तुलना में अधिक विशिष्ट नहीं है, जिसका अर्थ यह है कि क्लास टेम्पलेट विशेषज्ञता प्राथमिक टेम्पलेट की तुलना में अधिक विशिष्ट नहीं है। इसलिए, जीसीसी अस्वीकार करने के लिए सही होगा।

0

पर विचार करें:

template <class T, T first, T... rest> 
struct X{}; 

template<class T, T... rest> 
struct X<T, rest...>{}; 

सटीक एक ही त्रुटि। first के बाद से rest पैक के पहले तत्व के रूप में व्याख्या किया जा सकता है, इससे इस तरह के विशेषज्ञता में कोई फर्क नहीं पड़ता है। यदि आप विशेषज्ञता में first जोड़ते हैं - ठीक है, यह प्राथमिक टेम्पलेट है। अपने विशेषज्ञता में आप first जोड़ सकते हैं, हालांकि:

//specialization 
template<typename T, 
     T first, 
     T... args> 
struct A<0, T, first, args...> { 
}; 
संबंधित मुद्दे