2017-08-04 14 views
5

क्या किसी भी तरह से sizeof(std::optional<double>) == 8 का उपयोग करके std :: वैकल्पिक को कार्यान्वित करना संभव है कि आप एनएएन में वर्णों को स्टोर कर सकते हैं, http://en.cppreference.com/w/cpp/numeric/math/nan देखें? क्या वहां कार्यान्वयन हैं? क्या यह मानक में उपलब्ध कार्यक्षमता के संदर्भ में किया जा सकता है?वैकल्पिक <double> 8-बाइट ऑब्जेक्ट के रूप में कार्यान्वित किया जा सकता है?

+3

'डबल' की संख्या 8 के आकार की गारंटी नहीं है। उदाहरण के लिए [कुछ प्लेटफ़ॉर्म] (https://www.arduino.cc/en/Reference/Double) 4 बाइट' डबल' का उपयोग करते हैं। शायद सवाल को 'sizeof (std :: वैकल्पिक ) == आकार (डबल)' के रूप में जाना जाना चाहिए। –

+0

सवाल यह है कि, क्या आप जानना चाहते हैं कि यह अभ्यास में अच्छा किया जा सकता है ताकि यह कुछ प्लेटफॉर्म पर भरोसेमंद हो? या आप जानना चाहते हैं कि यह 100% मानक अनुपालन के तरीके से किया जा सकता है या नहीं? जवाब हां और नहीं है। –

+0

आप 'has_value' के बजाय' std :: isnan' का उपयोग कर सकते हैं और आपके पास जो भी हो वह है। – Dani

उत्तर

1

मुझे नहीं लगता कि यह किया जा सकता है क्योंकि नाइन में अतिरिक्त बिट्स पर उपयोग करने और भरोसा करने से कार्यक्रमों को रोकने से कोई नियम नहीं है। फिर यदि आप जादू संख्या को optional में संग्रहीत करते हैं तो ऐसा लगता है कि यह एप्लिकेशन के विशेष NaN के बजाय मौजूद नहीं है।

+0

क्या होगा यदि जादू संख्या कानूनी 'डबल' मान नहीं थी? ऐसा कोई नियम नहीं है जो कहता है कि 'डबल' में फ़िट होने वाले बिट मानों के हर संभव संयोजन को कानूनी 'डबल' मान का प्रतिनिधित्व करना चाहिए। गलती बिट पैटर्न की अनुमति है और यदि कोई कारण है 'वैकल्पिक' उनका उपयोग नहीं कर सका, तो आपका जवाब यह नहीं बताता कि यह क्या है। –

1

उत्तर बहु ​​गुना है।

सबसे पहले, यह मानक में उपलब्ध कार्यक्षमता के साथ कार्यान्वित नहीं किया जा सकता है, क्योंकि मानक फ़्लोटिंग पॉइंट कार्यान्वयन के कुछ भी नहीं कहता है।

दूसरा, आईईईई 754 फ्लोटिंग पॉइंट्स के लिए आप युगल के लिए std::optional विशेषज्ञता करके अपना वैकल्पिक कार्यान्वित कर सकते हैं। हालांकि, इसका मतलब यह होगा कि आप मूल्यों की अपनी सीमा से वैध मान (NaN कुछ अंकगणितीय परिचालनों द्वारा उत्पादित परिणाम) को बहिष्कृत करते हैं। हालांकि, आईईईई 754 में गहराई से डाइविंग, आप विशिष्ट NaN प्रतिनिधित्व (उनमें से बहुत सारे हैं!) को नो-वैल्यू के रूप में चुन सकते हैं।

+0

मानक टेम्पलेट्स को मानक मानने तक मानक अस्वीकार नहीं करता है जब तक कम से कम एक तर्क उपयोगकर्ता परिभाषित प्रकार नहीं है? साथ ही, 'std :: वैकल्पिक' की आवश्यकताओं को पूरा करने के लिए अभी भी विशेषज्ञता की आवश्यकता होगी। – user2079303

+0

@ user2079303 हां यह करता है। 'डबल' के लिए 'वैकल्पिक' विशेषज्ञता विशेष यूबी होगी। हालांकि, आप अपना खुद का प्रकार बना सकते हैं जिसमें एक डबल होता है, और स्पष्ट रूप से इसमें परिवर्तित होता है और इसका उपयोग करता है। हालांकि कुछ स्थितियों में शायद परेशान (टेम्पलेट एज मामलों)। –

+0

@ user2079303 ठीक है, इस समय आपका कोड पोर्टेबल नहीं है, इसलिए मुझे सामान्य मानक समस्याओं के बारे में बहुत अधिक परवाह नहीं है। यह केवल इसलिए प्रतिबंधित है क्योंकि गैर-प्रयोक्ता-परिभाषित प्रकारों के लिए कार्यान्वयन (या कार्यों के मामले में अधिभार) को लागू करने की अनुमति है, इसलिए यह सुनिश्चित करने के लिए पर्याप्त होगा कि आपका कार्यान्वयन 'वैकल्पिक ' के लिए ऐसा नहीं करता है और आगे बढ़ता है। – SergeyA

1

std::optional को इस तरह कार्यान्वित करना संभव नहीं है क्योंकि यह पोस्ट-स्थितियों के विपरीत है जो निर्दिष्ट करता है कि वर्ग (टेम्पलेट) कैसे व्यवहार करता है। उदाहरण के लिए: std::optionalअगर यह प्रकार T के एक मूल्य के साथ आरंभ नहीं हो जाता एक मूल्य के शामिल है, लेकिन आपके द्वारा सुझाए गए std::optional<double> एक मूल्य नहीं होते हैं अगर यह होता है कि विशेष NaN मूल्य आपके द्वारा चुनी गई एक मूल्य के साथ प्रारंभ किया गया था।

इसके अलावा, सी ++ मानक गारंटी नहीं देता/आवश्यक है कि फ़्लोटिंग पॉइंट प्रकार NaN का समर्थन करता है (शांत) NaN। कुछ सिस्टम नहीं करते हैं।

विभिन्न अर्थशास्त्र के साथ अपने स्वयं के गैर मानक optional कक्षा को लागू करना निश्चित रूप से संभव है। बेशक, आप कार्यान्वयन परिभाषित तथ्य पर भरोसा करेंगे कि NaN मान मौजूद हैं। आपको फ़्लोटिंग पॉइंट प्रस्तुति के ज्ञान पर भी भरोसा करना है, क्योंकि जहां तक ​​मुझे पता है, नाएन पेलोड का निरीक्षण करने के लिए कोई मानक उपयोग नहीं है - केवल एक विशिष्ट पेलोड वाला मूल्य उत्पन्न करने के लिए।

+0

क्या होगा यदि विशेष NaN मान 'डबल' के लिए कानूनी मान नहीं था लेकिन फिर भी फिट बैठता है। उदाहरण के लिए, एक प्लेटफॉर्म की कल्पना करें जहां प्रत्येक 'डबल' के पास अतिरिक्त "डबल डबल" बिट होता है जिसका उपयोग केवल डीबग उद्देश्यों के लिए आंतरिक रूप से किया जाता था। 'वैकल्पिक' इस बिट को सह-चयन क्यों नहीं कर सका? –

+0

@ डेविडस्वार्टज़ मुझे लगता है, अगर सिस्टम ने विशेष रूप से संकलक के लिए यह बिट आरक्षित किया है, तो यह चाहता है। और मुझे लगता है कि संभावना काफी हद तक अकादमिक है :) – user2079303

+0

आप कितने निश्चित हैं कि हर संभव बिट पैटर्न 'डबल' मान से मेल खाता है जो उत्पादन करना संभव है? आपको केवल एक पैटर्न चाहिए जो नहीं करता है। –

0

एक अच्छा टेक्स्ट एडिटर और कट-पेस्ट का उपयोग करके आप जो प्रस्तावित करते हैं उसे कार्यान्वित करना अपेक्षाकृत छोटा है। चूंकि यह एक अच्छा विचार है, इसलिए मैंने इसे अपने टूल बॉक्स में जोड़ने का फैसला किया है। मेरा मुख्य प्रेरणा यह है कि std :: वैकल्पिक <> एस बल्कि बड़े हैं, और इस प्रकार std :: variant <> प्रकारों में उपयोग करने के लिए व्यावहारिक नहीं हैं।

#include <type_traits> 
#include <limits> 
#include <exception> 

class bad_optional_flt_access 
    : public std::exception 
{ 
public: 
    bad_optional_flt_access() {} 

    const char* what() const noexcept override 
    { 
     return "bad optional float access"; 
    } 
}; 

template <typename Float, bool = std::is_floating_point<Float>::value> 
class optional_flt; 

template <typename Float> 
class optional_flt<Float, false> {}; 

template <typename Float> 
class optional_flt<Float, true> 
{ 
public: 
    constexpr optional_flt() noexcept : value_(std::numeric_limits<Float>::quiet_NAN()) {} 
    constexpr optional_flt(const Float& val) noexcept : value_(val) {} 

    template<typename T> 
    constexpr optional_flt(const T& val) noexcept : value_(Float(val)) {} 

    constexpr bool has_value() const noexcept 
    { 
     return value_ != std::numeric_limits<Float>::quiet_NAN(); 
    } 

    void reset() noexcept { value_ = std::numeric_limits<Float>::quiet_NAN(); } 

    constexpr void swap(optional_flt& other) noexcept { std::swap(value_, other.value_); } 

    constexpr operator bool() const noexcept { return has_value(); } 

    Float& value() & 
    { 
     if (!has_value()) 
      throw bad_optional_flt_access(); 
     return value_; 
    } 

    Float&& value() && 
    { 
     if (!has_value()) 
      throw bad_optional_flt_access(); 
     return value_; 
    } 

    constexpr const Float& value() const & 
    { 
     if (!has_value()) 
      throw bad_optional_flt_access(); 
     return value_; 
    } 

    Float& operator *() & noexcept { return value_; } 
    constexpr const Float& operator *() const & noexcept{ return value_; } 

    template< class U > 
    constexpr Float value_or(U&& default_value) const& 
    { 
     return (has_value()) ? value_ : default_value; 
    } 

    template< class U > 
    constexpr Float value_or(U&& default_value) && 
    { 
     return (has_value()) ? value_ : default_value; 
    } 

private: 
    Float value_; 
}; 

template< class T, class U > 
constexpr bool operator==(const optional_flt<T>& lhs, const optional_flt<U>& rhs) 
{ 
    return lhs.value() == rhs.value(); 
} 

template< class T, class U > 
constexpr bool operator!=(const optional_flt<T>& lhs, const optional_flt<U>& rhs) 
{ 
    return lhs.value() != rhs.value(); 
} 

template< class T, class U > 
constexpr bool operator<(const optional_flt<T>& lhs, const optional_flt<U>& rhs) 
{ 
    return lhs.value() < rhs.value(); 
} 

template< class T, class U > 
constexpr bool operator<=(const optional_flt<T>& lhs, const optional_flt<U>& rhs) 
{ 
    return lhs.value() <= rhs.value(); 
} 

template< class T, class U > 
constexpr bool operator>(const optional_flt<T>& lhs, const optional_flt<U>& rhs) 
{ 
    return lhs.value() > rhs.value(); 
} 

template< class T, class U > 
constexpr bool operator>=(const optional_flt<T>& lhs, const optional_flt<U>& rhs) 
{ 
    return lhs.value() >= rhs.value(); 
} 

template<typename T> 
constexpr optional_flt<T> make_optional_flt(const T& x) 
{ 
    return optional_flt<T>(x); 
} 

int main() 
{ 
    int i = 2; 

    auto x = optional_flt<float>{i}; 
    auto y = optional_flt<double>(2.5); 


    return (*x < .5) ? sizeof(optional_flt<double>) : 1; 
} 

कोड ऊपर gcc -std=c++11, clang -std=c++14, और cl /std:c++11 संगत है।

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

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