जीसीसी सही है प्रकार कटौती के लिए नजरअंदाज कर दिया जाता है। एक से थोड़ा सरल उदाहरण से
आइए शुरू, और बाद में साबित होता है कि मूल उदाहरण एक ही पैटर्न इस प्रकार है:
template<typename T>
void bar(T const&)
{
// Shall not fire
static_assert(std::is_same<T, int>::value, "Error!");
}
int main()
{
int x = 0;
bar(x); // 1 - Assertion won't fire
int const y = 0;
bar(y); // 2 - Assertion won't fire
}
यहाँ क्या हो रहा है? सबसे पहले, प्रति § 14.8.2.1/3:
[...] यदि पी संदर्भ प्रकार है, तो पी द्वारा संदर्भित प्रकार का प्रकार कटौती के लिए उपयोग किया जाता है। [...]
इसका मतलब यह है कि प्रकार कटौती और int const
के खिलाफ (मामले 2 में) (मामले 1 में) int
के खिलाफ T const
बनाने का प्रयास करेगा। दूसरे मामले में, T
के लिए int
को प्रतिस्थापित करने से एक परिपूर्ण मिलान मिलेगा, इसलिए यह आसान है; पहले मामले में, हमारे पास const
एक परिपूर्ण मिलान करने के लिए हमारे रास्ते पर जा रहा है। लेकिन यह वह जगह है जहां § 14.8.2.1/4 खेलने में आता है:
[...] मूल पी एक संदर्भ प्रकार है, तो निष्कर्ष निकाला एक (यानी, प्रकार संदर्भ द्वारा कहा गया है) हो सकता है अधिक सीवी योग्य तब्दील ए से [...]
यहाँ, की जगह T
के लिए int
हमें एक निष्कर्ष निकाला int const
, जो और अधिक सीवी योग्य से int
(के प्रकार है देता है तर्क x
)। लेकिन यह उपरोक्त § 14.8.2.1/4 के कारण स्वीकार्य है, इसलिए इस मामले में भी T
int
होने के लिए घटाया गया है।
चलो अब अपने मूल उदाहरण से निपटने (बस थोड़ा सा समायोजित, लेकिन हम मूल संस्करण के अंत में मिल जाएगा):
template<typename T>
void bar(T const&)
{
// Does not fire in GCC, fires in VC11. Who's right?
static_assert(std::is_same<T, char[4]>::value, "Error!");
}
int main()
{
char x[] = "foo";
bar(x);
char const y[] = "foo";
bar(y);
}
अलावा तथ्य यह है कि मैं char []
साथ int
प्रतिस्थापित से, इस उदाहरण है और मेरी पहला उदाहरण संरचना में समान हैं। क्यों इस तुल्यता रखती है देखने के लिए, (है, जो पर आग नहीं करता है किसी भी संकलक की उम्मीद के रूप में) नीचे दावे पर विचार करें: पैरा में
// Does not fire
static_assert(
std::is_same<
std::add_const<char [4]>::type,
char const[4]
>::value, "Error");
सी ++ 11 स्टैंडर्ड जनादेश इस व्यवहार 3.9.3/2 :
किसी भी सीवी-क्वालिफायर एक सरणी प्रकार के लिए लागू किया सरणी तत्व प्रकार, नहीं सरणी प्रकार (8.3.4) प्रभावित करते हैं।
पैरा 8.3.4/1 भी निर्दिष्ट करता है:
[...] फार्म "NT के सीवी-क्वालीफायर-सेक सरणी" किसी भी प्रकार की "एन सीवी की सरणी लिए निकाला जाता है -क्वालिफायर-सेक टी ", और इसी तरह" टी के अज्ञात बंधन की सरणी "के लिए। सरणी के लिए वैकल्पिक विशेषता-विनिर्देशक-सीईसी appertains। [उदाहरण:
typedef int A[5], AA[2][3];
typedef const A CA; // type is “array of 5 const int”
typedef const AA CAA; // type is “array of 2 array of 3 const int”
अंत उदाहरण] [ध्यान दें: एक "एन सीवी-क्वालीफायर-सेक टी की सरणी" सीवी योग्य प्रकार है; 3.9.3 देखें। -जेंड नोट]
चूंकि अब यह स्पष्ट है कि दो उदाहरण समान पैटर्न प्रदर्शित करते हैं, यह एक ही तर्क लागू करने के लिए समझ में आता है। और यह हमें एक ही तर्क पथ के माध्यम से नेतृत्व करेंगे।
टाइप कटौती करते समय, T const
पहले मामले में char[4]
और दूसरे मामले में char const[4]
के विरुद्ध मेल खाता है।
दूसरे मामले में, T = char[4]
एक सही मैच पैदा करता है, क्योंकि प्रतिस्थापन के बाद T const
char const[4]
बन जाता है। पहले मामले में, निष्कर्ष निकाला A
एक बार फिर से अधिक है कि T
पैदावार char const[4]
के लिए char[4]
प्रतिस्थापन में सीवी योग्य मूल A
से है। लेकिन फिर, इसे 14.8.2.1/4 तक अनुमति है, इसलिए T
को char[4]
के रूप में घटाया जाना चाहिए।
अंत में, अपने मूल उदाहरण के लिए।
template<typename T>
void foo(T const&)
{
// Shall not fire
static_assert(std::is_same<T, char[4]>::value, "Error!");
}
int main()
{
foo("str"); // Shall not trigger the assertion
}
दोनों शिकायत कर रहे हैं कोई 'foo' परिभाषित .... – UmNyobe
@UmNyobe: स्ट्रिंग शाब्दिक
"str"
भी टाइपchar const[4]
,T
char [4]
, जिसका अर्थ है होना करने के लिए निष्कर्ष निकाला जाना चाहिए कि जीसीसी सही है के बाद से हाँ, मुझे पता है, यह टाइप केवल – FrozenHeart@UmNyobe मेरा मतलब है कि किस प्रकार इस मामले में होना चाहिए मुद्रित करने के लिए की जरूरत थी - चार [4] या चार स्थिरांक [4]? – FrozenHeart