क्या 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.