क्या T को `std :: डिक्लेव <T>` में उपयोग करने के लिए एक पूर्ण प्रकार होना चाहिए?


11

इस उदाहरण पर विचार करें ( यहाँ से आ रहे हैं ):

#include <type_traits>
#include <iostream>
template <typename U>
struct A {
};

struct B {
   template <typename F = int>
   A<F> f() { return A<F>{}; }

   using default_return_type = decltype(std::declval<B>().f());
};

int main()
{
    B::default_return_type x{};
    std::cout << std::is_same< B::default_return_type, A<int>>::value;
}

यह gcc9.2 पर कोई त्रुटि नहीं है, लेकिन gcc7.2 और clang 10.0.0 Bको पूरा नहीं होने के बारे में शिकायत करता है । Clangs त्रुटि है:

prog.cc:11:58: error: member access into incomplete type 'B'
   using default_return_type = decltype(std::declval<B>().f());
                                                         ^
prog.cc:7:8: note: definition of 'B' is not complete until the closing '}'
struct B {
       ^
prog.cc:16:8: error: no type named 'default_return_type' in 'B'
    B::default_return_type x{};
    ~~~^
prog.cc:17:35: error: no member named 'default_return_type' in 'B'
    std::cout << std::is_same< B::default_return_type, A<int>>::value;
                               ~~~^

1
प्रश्न शीर्षक त्रुटि से मेल नहीं खाता है? मेरे लिए, ऐसा लगता है कि जीसीसी शिकायत करता है .f()। यह समझ आता है; अपूर्ण प्रकार Bका कोई सदस्य नहीं है f।
— MSalters

@MSalters मैंने भी यही सोचा था, लेकिन फिर यहाँ असली समस्या क्या है? मुझे लगता है कि एक बार जब आप इससे एक उदाहरण प्राप्त std::declvalकरते हैं तो इससे कोई फर्क नहीं पड़ता कि क्या प्रकार पूर्ण था या नहीं (और मुझे लगता है कि मैं इसके साथ गलत हूं)
— idclev 463035818

[expr.ref] / 2 (C ++ 11) वर्ग के सदस्य अभिगम के बारे में कहता है: "पहले विकल्प (डॉट) के लिए पहली अभिव्यक्ति में पूर्ण वर्ग प्रकार होगा" । और Bन तो पूर्ण माना जाता है और न ही पूर्ण माना जाता है alias-declaration।
— भाषा वकील


1
@LanguageLawyer ठीक है तो मैं मानता हूं कि मेरी व्याख्या बंद थी और ऐसा लगता है कि सी ++ 11 के बाद से कुछ बदल गया है जो उपरोक्त मानकों को नए मानकों में नहीं बल्कि सी ++ 11 में बनाता है। क्या आप कोई उत्तर लिखना चाहेंगे?
— आइडलव्यू ४६३०३५18१

जवाबों:


9

त्रुटि का स्रोत नहीं है std::declval, लेकिन अधूरा वर्ग सदस्य पहुंच है।

CWG1836 के संकल्प तक 2.5 साल पहले विलय कर दिया गया था, तब तक मानक को कक्षा के सदस्य अभिगम अभिव्यक्ति ( E1.E2) में पूरा होना आवश्यक था ।
[expr.ref] / C ++ 11 में 2 :

पहले विकल्प (डॉट) के लिए पहली अभिव्यक्ति में पूर्ण वर्ग प्रकार होगा।

[expr.ref] / C ++ 17 में 2 :

पहले विकल्प (डॉट) के लिए पहला एक्सप्रेशन एक ग्लव्यू होगा जिसमें पूरा क्लास टाइप होगा।

और एक वर्ग को alias-declarationअपने भीतर पूरा नहीं माना जाता है member-specification।
[class.mem] / C ++ 17 में 6 :

एक वर्ग एक पूरी तरह से परिभाषित ऑब्जेक्ट प्रकार ([basic.types]) (या पूर्ण प्रकार) समापन पर माना जाता है }की वर्ग-विनिर्देशक । क्लास मेंबर-स्पेसिफिकेशन के भीतर, फंक्शन बॉडीज़, डिफॉल्ट तर्कों, नॉइसेप्ट-स्पेसिफायर एस और डिफॉल्ट मेंबर इनिशियलाइज़र्स (नेस्टेड क्लासेस में ऐसी चीज़ों को मिलाकर) को क्लास पूरा माना जाता है । अन्यथा इसे अपने वर्ग के सदस्य-विनिर्देश के भीतर अधूरा माना जाता है ।


8

से [declval] :

टिप्पणियां: टेम्पलेट पैरामीटर Tकी declvalएक अधूरी प्रकार हो सकता है।

C ++ 11 के बाद से यह शब्दांकन मौजूद है (इसलिए कंपाइलरों के लिए पहले के मानक के अनुरूप होना संभव नहीं है)


बहुत बढ़िया, जो मुझे उम्मीद थी।
— Gcc की

@ पूर्ववार्ता_463035818: मेरा पहला विचार यह था कि Tपूरी तरह से एक पूर्ण प्रकार होना चाहिए। खुशी है कि मैंने मानक की जांच की।
— एंडीज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.