क्या क्लैंग कोड को अस्वीकार करने के लिए सही है जिसमें वर्ग टेम्पलेट के नेस्टेड वर्ग को केवल विशेषज्ञता के माध्यम से परिभाषित किया गया है?


17

निम्नलिखित वर्ग टेम्पलेट को देखते हुए:

template<typename T>
struct Outer
{
    struct Inner;

    auto f(Inner) -> void;
};

हम Innerप्रत्येक विशेषज्ञता के लिए अलग से परिभाषित करते हैं Outer:

template<>
struct Outer<int>::Inner {};

template<>
struct Outer<double>::Inner {};

और फिर सदस्य समारोह fको सभी विशिष्टताओं के लिए एक बार परिभाषित करें Outer:

auto Outer<T>::f(Inner) -> void
{

}

लेकिन क्लैंग (9.0.0) शिकायत करती है:

error: variable has incomplete type 'Outer::Inner'

auto Outer<T>::f(Inner) -> void

                      ^

हम कंपाइलर एरर को Innerअन्य सभी स्पेशलाइज़ेशन की परिभाषा प्रदान करके भी मिटा सकते हैं Outer:

template<typename T>
struct Outer<T>::Inner {};

या fप्रत्येक विशेषज्ञता के लिए अलग से परिभाषित करके :

template<>
auto Outer<int>::f(Inner) -> void
{

}

template<>
auto Outer<double>::f(Inner) -> void
{

}

जीसीसी और एमएसवीसी दोनों प्रारंभिक कोड को स्वीकार करते हैं, जो प्रश्न पूछते हैं; क्या यह एक क्लैंग बग है या क्या यह तीनों में से एकमात्र अनुरूप कार्यान्वयन है?

कंपाइलर एक्सप्लोरर पर प्रयास करें


इनर के विशेषज्ञ अप्रासंगिक हैं, उन्हें हटाने से संकलन परिणाम नहीं बदलता है।
एन। 'सर्वनाम' मी।

@ n.'pronouns'm। मुझे नहीं पता तुम्हारा क्या मतलब है। दोनों अन्य सभी विशिष्टताओं की परिभाषा जोड़ते Innerहैं और प्रत्येक विशेषज्ञता के लिए अलग-अलग परिभाषित fकरते हुए संकलन त्रुटि को हल करते हैं।
invexed'

आइए इसे फिर से पढ़ें: उन्हें हटाने से संकलन परिणाम नहीं बदलता है । जोड़ना, हटाना नहीं। gcc clang
एन। 'सर्वनाम' मी।

@ n.'pronouns'm। मैं देख रहा हूं कि आपका क्या मतलब है, लेकिन यह अभी भी एक अजीब टिप्पणी है। मेरे प्रश्न का बिंदु यह था कि प्रदान किए जाने वाले Innerप्रत्येक विशेषज्ञता के लिए परिभाषाओं के बावजूद एक अपूर्ण प्रकार के रूप में रिपोर्ट किया Outerजा रहा है। Innerयदि आप इसकी परिभाषा को हटाते हैं तो स्पष्ट रूप से (सही ढंग से) एक अपूर्ण प्रकार होगा।
invexed'

"स्पष्ट रूप से इनर (सही ढंग से) एक अधूरा प्रकार होगा यदि आप इसकी परिभाषा (ओं) को हटाते हैं।" नहीं। यह बिल्कुल भी नहीं है। एक विशेषज्ञता पूरी तरह से अलग टेम्पलेट है और यह मुख्य टेम्पलेट को बिल्कुल भी प्रभावित नहीं करता है।
n। 'सर्वनाम' एम।

जवाबों:


4

मेरा मानना ​​है कि क्लैंग आपके कोड को अस्वीकार करने के लिए गलत है। हमें अपने आप से पूछना चाहिए कि आपके कार्य की घोषणा और परिभाषा किस तरह की है

auto f(typename T::Inner) -> void;

// ...

template<typename T>
auto Outer<T>::f(typename T::Inner) -> void
{ }

इस उदाहरण में, T::Innerस्पष्ट रूप से एक निर्भर प्रकार है। इसलिए क्लैंग यह नहीं मान सकता है कि यह अधूरा है। क्या आपके उदाहरण में वही सही है? मैं बस यही कहूँगा। हमारे लिए यह मानक में है:

[Temp.dep.type]

5 एक नाम वर्तमान तात्कालिकता का एक सदस्य है यदि यह है

  • एक अयोग्य नाम जिसे देखते समय, एक वर्ग के कम से कम एक सदस्य को संदर्भित करता है जो कि वर्तमान तात्कालिकता या उसके गैर-निर्भर आधार वर्ग है। [नोट: यह केवल तब हो सकता है जब किसी वर्ग टेम्प्लेट की परिभाषा से घिरे दायरे में नाम की तलाश की जा रही है। - अंतिम नोट]
  • ...

एक नाम वर्तमान तात्कालिकता का एक आश्रित सदस्य है यदि यह वर्तमान तात्कालिकता का सदस्य है, जिसे देखते समय, उस वर्ग के कम से कम एक सदस्य को संदर्भित करता है जो वर्तमान तात्कालिकता है।

9 एक प्रकार निर्भर है अगर यह है

  • ...
  • अज्ञात विशेषज्ञता के सदस्य,
  • एक नेस्टेड क्लास या एन्यूमरेशन जो वर्तमान तात्कालिकता का एक आश्रित सदस्य है,
  • ...

तो पैरा 9 में पहली गोली मामले को कवर करती है typename T::Inner। वह एक आश्रित प्रकार है।

इस बीच आपका मामला दूसरी गोली से ढंका है। Outer::Innerएक ऐसा नाम है जो वर्तमान तात्कालिकता में पाया जाता है Outer, इसके अलावा यह Outerअपने अंदर पाया जाता है, न कि बेस क्लास में। यह इसे वर्तमान तात्कालिकता का एक निर्भर सदस्य बनाता है। यह नाम एक नेस्टेड क्लास को संदर्भित करता है। जिसका अर्थ है दूसरी बुलेट में सभी शर्तें लागू होती हैं, इस प्रकार Outer::Innerएक निर्भर प्रकार भी बनता है!

चूंकि हमारे पास दोनों मामलों में खुद पर निर्भर प्रकार है, इसलिए कंपाइलरों को उन्हें समान प्रकार के रूप में व्यवहार करना चाहिए। मेरा निष्कर्ष यह है कि जीसीसी और एमएसवीसी सही हैं।


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