2015-01-22 6 views
11

के साथ टाइप पर is_constructible std::is_constructible के लिए एक निजी या संरक्षित विनाशक के साथ अपेक्षित परिणाम क्या है?std :: गैर-सार्वजनिक विनाशक

उदाहरण के लिए, मैं अभी भी ढेर पर इस तरह के एक वस्तु केवल एक दोस्त यह मुक्त कर सकते हैं भले ही निर्माण कर सकते हैं:

#include <type_traits> 

class Foo 
{ 
    friend void freeFoo(Foo*); 
public: 
    Foo() 
    {} 
private: 
    // Destructor is private! 
    ~Foo() 
    {} 
}; 

void freeFoo(Foo* f) 
{ 
    delete f; // deleting a foo is fine here because of friendship 
} 

int main() 
{ 
    Foo* f = new Foo(); 
    // delete f; // won't compile: ~Foo is private 
    freeFoo(f); // fine because of friendship 


    if(!std::is_constructible<Foo>::value) 
    { 
     std::cout << "is_constructible failed" << std::endl; 
    } 
} 

is_constructible के लिए अंतिम जाँच के दोनों जीसीसी और विजुअल C++ (gcc demo on coliru) पर असफल हो जायेगी।

क्या मानक द्वारा आवश्यक व्यवहार है? यदि हां, तो क्या यह जांचने का कोई तरीका है कि किस प्रकार का विशिष्ट निर्माता है, भले ही विनाशक पर पहुंच निर्दिष्टकर्ता हो?

+0

संबंधित: https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/bPwd3UkZa6w – Caramiriel

+0

@ कैमरिरिल दुर्भाग्यवश यह समस्या को सीधे संबोधित नहीं कर रहा है। 'is_destructible' स्पष्ट रूप से विनाशक की पहुंच पर निर्भर करता है, जो यहां मामला नहीं है। – Columbo

उत्तर

12

सी ++ 14 एफडी is_constructible को परिभाषित करता है इस प्रकार है:

को देखते हुए निम्नलिखित समारोह घोषणा:

template <class T> 
add_rvalue_reference_t<T> create() noexcept; 

एक टेम्पलेट विशेषज्ञता के लिए विधेय हालत is_constructible<T, Args...> संतुष्ट किया जाएगा यदि और केवल यदि निम्नलिखित परिवर्तनीय परिभाषा का कुछ आविष्कार परिवर्तनीय t:

के लिए अच्छी तरह से गठित किया जाएगा 10
T t(create<Args>()...); 

पहुँच जाँच के रूप में एक संदर्भ T और Args में से किसी के साथ कोई संबंध में अगर किया जाता है। के तत्काल संदर्भ की केवल वैधता को वैरिएबल प्रारंभिक माना जाता है। [नोट: प्रारंभ के मूल्यांकन ऐसे वर्ग टेम्पलेट विशेषज्ञता के इन्स्टेन्शियशन और समारोह टेम्पलेट विशेषज्ञताओं, परोक्ष-परिभाषित प्रकार्य की पीढ़ी, और इतने पर के रूप में साइड इफेक्ट हो सकती है। इस तरह के साइड इफेक्ट्स "तत्काल संदर्भ" में नहीं हैं और परिणामस्वरूप बीमार होने का परिणाम हो सकता है। अंत टिप्पणी]

अब प्रश्न अनिवार्य रूप से कम कर देता है के लिए "चर प्रारंभ की तत्काल संदर्भ में नाशक कॉल है?" [कक्षा।dtor]/11:

एक नाशक परोक्ष

  • कार्यक्रम समाप्ति (3.6.3) पर स्थिर भंडारण अवधि (3.7.1) के साथ एक निर्माण वस्तु के लिए, शुरू हो जाती है
  • एक निर्माण के लिए
  • स्वत: भंडारण अवधि (3.7.3) के साथ ऑब्जेक्ट जब एक ऑब्जेक्ट बनाया गया है (6.7),
  • एक निर्मित अस्थायी ऑब्जेक्ट के लिए जब उसका जीवनकाल समाप्त होता है (12.2)।

प्रत्येक मामले में, मंगलाचरण के संदर्भ वस्तु का निर्माण के संदर्भ है।

इस प्रकार नाशक मंगलाचरण निर्माण के संदर्भ में है (जो संभवतः यहाँ प्रारंभ करने के लिए पर्याय बन गया है), जिसका मतलब है कि यह माना जाता है और कारण बनता विशेषता false वापस जाने के लिए।
मेरा मानना ​​है कि इसे अनिर्धारित किया जाना चाहिए (उदा। तत्काल स्पष्ट रूप से तत्काल संदर्भ नहीं?), लेकिन सहजता से मैं NotDestructible() को अभिव्यक्ति को चिह्नित करने के लिए एक अनुरूप कार्यान्वयन की अपेक्षा करता हूं - या तो एसएफआईएनएई-अनुकूल या नहीं (अधिमानतः पूर्व)। हालांकि, कभी अच्छी तरह से गठित नहीं किया।
Clang with libc++, libstdc++ and GCC do say that it's invalid, SFINAE-friendly


यदि हां, तो वहाँ प्रकार एक विशिष्ट निर्माता है, नाशक पर पहुँच विनिर्देशक की परवाह किए बिना कि क्या जांच करने के लिए किसी भी तरह से है?

new का उपयोग करने के बारे में क्या?

template <typename T, typename... Args> 
class is_only_constructible 
{ 
    template <typename, typename=void> struct test : std::false_type {}; 
    template <typename U> 
    struct test<U, decltype(void(new U(std::declval<Args>()...)))> : std::true_type {}; 

public: 
    static constexpr bool value = test<T>::value; 
}; 

Demo। लगातार लक्षणों को आसानी से स्थापित किया जा सकता है: is_only_constructible विशेषता लें और इसे is_destructible के साथ संयोजित करें (स्पष्ट रूप से उत्तरार्द्ध false निजी विनाशकों के साथ संयुक्त होने पर)।

+0

मैं सोच रहा हूं: यदि समिति का इरादा 'is_constructible :: मूल्य' उपज 'सत्य' था, तब भी जब' टी' का विनाशक पहुंच योग्य नहीं है (जो आप दावा करते हैं), यह निर्दिष्ट क्यों नहीं करते 'नई' अभिव्यक्ति के संदर्भ में विशेषता का व्यवहार? –

+0

@AndyProwl यह मेरा मतलब नहीं है।मुझे लगता है कि समिति ने इस मामले पर सही ढंग से विचार नहीं किया था और इस प्रकार पाठ को अनिर्धारित किया गया था। – Columbo

+0

मैं देखता हूं। मैंने शायद इस कथन को गलत समझा: "जहां तक ​​मैं देख सकता हूं, एक विनाशक कॉल प्रारंभिक संदर्भ के तत्काल संदर्भ में नहीं है और इस प्रकार इसे नहीं माना जाना चाहिए"। –

5

का हवाला देते हुए पैरा [meta.unary.prop] सी ++ मानक (ड्राफ्ट N4296) का/7:

को देखते हुए निम्नलिखित समारोह घोषणा:

template <class T> 
add_rvalue_reference_t<T> create() noexcept; 

एक टेम्पलेट विशेषज्ञता के लिए विधेय हालत is_constructible<T, Args...> संतुष्ट होगा अगर केवल निम्न परिवर्तनीय परिभाषा कुछ आविष्कारशील चर t:

T t(create<Args>()...); 
के लिए अच्छी तरह से बनाई गई होगी

दूसरे शब्दों में, is_constructible<T, Args...>::valuefalse उत्पन्न करता है यदि विनाशक पहुंच योग्य नहीं है।

+0

तो सवाल के दूसरे भाग के बारे में क्या है: क्या यह जांचने का कोई तरीका है कि किस प्रकार का डिस्ट्रक्टर पर पहुंच विनिर्देशक के बावजूद कोई विशिष्ट कन्स्ट्रक्टर है या नहीं? – ComicSansMS

+0

@ कॉमिकसैनएमएस: मुझे डर है कि मैं उस हिस्से का जवाब नहीं दे सकता (कम से कम, मेरे सिर के शीर्ष से नहीं), हालांकि मुझे संदेह है कि जवाब "नहीं" है। –

+0

यही वह था जिसे मैं डरता था। एक सामान्य सदस्य समारोह के अस्तित्व की जांच करना मुश्किल नहीं है, लेकिन रचनाकार मुश्किल हैं। मुझे लगता है कि इसे 'type_traits' में एक निरीक्षण माना जा सकता है। – ComicSansMS

संबंधित मुद्दे