एक भेदभाव संघ की खोज/टैग किए गए संस्करण मैं निष्कर्ष निकालना "नाशक संकलन समय पर कुछ शर्तों पर तुच्छ बनाने" के रूप में इस तरह के एक सुविधा में विशेष आवश्यकता नहीं है। मैं SFINAE किसी तरह का या की तरह (स्यूडोकोड) कुछ मतलब है:सशर्त तुच्छ नाशक
template< typename ...types >
struct X
{
~X() = default((std::is_trivially_destructible<types>{} && ...))
{
// non-trivial code here
}
};
इसका मतलब है कि अगर default(*)
में हालत true
है, तो नाशक की परिभाषा ~X() = default;
के बराबर है, लेकिन अगर यह है false
तो { // ... }
शरीर बजाय प्रयोग किया।
#pragma once
#include <type_traits>
#include <utility>
#include <experimental/optional>
#include <cassert>
template< typename ...types >
class U;
template<>
class U<>
{
U() = delete;
U(U &) = delete;
U(U const &) = delete;
U(U &&) = delete;
U(U const &&) = delete;
void operator = (U &) = delete;
void operator = (U const &) = delete;
void operator = (U &&) = delete;
void operator = (U const &&) = delete;
};
template< typename first, typename ...rest >
class U< first, rest... >
{
struct head
{
std::size_t which_;
first value_;
template< typename ...types >
constexpr
head(std::experimental::in_place_t, types &&... _values)
: which_{sizeof...(rest)}
, value_(std::forward<types>(_values)...)
{ ; }
template< typename type >
constexpr
head(type && _value)
: head(std::experimental::in_place, std::forward<type>(_value))
{ ; }
};
using tail = U<rest...>;
union
{
head head_;
tail tail_;
};
template< typename ...types >
constexpr
U(std::true_type, types &&... _values)
: head_(std::forward<types>(_values)...)
{ ; }
template< typename ...types >
constexpr
U(std::false_type, types &&... _values)
: tail_(std::forward<types>(_values)...)
{ ; }
public :
using this_type = first; // place for recursive_wrapper filtering
constexpr
std::size_t
which() const
{
return head_.which_;
}
constexpr
U()
: U(typename std::is_default_constructible<this_type>::type{}, std::experimental::in_place)
{ ; }
U(U &) = delete;
U(U const &) = delete;
U(U &&) = delete;
U(U const &&) = delete;
template< typename type >
constexpr
U(type && _value)
: U(typename std::is_same< this_type, std::decay_t<type> >::type{}, std::forward<type>(_value))
{ ; }
template< typename ...types >
constexpr
U(std::experimental::in_place_t, types &&... _values)
: U(typename std::is_constructible< this_type, types... >::type{}, std::experimental::in_place, std::forward<types>(_values)...)
{ ; }
void operator = (U &) = delete;
void operator = (U const &) = delete;
void operator = (U &&) = delete;
void operator = (U const &&) = delete;
template< typename type >
constexpr
void
operator = (type && _value) &
{
operator std::decay_t<type> &() = std::forward<type>(_value);
}
constexpr
explicit
operator this_type &() &
{
assert(sizeof...(rest) == which());
return head_.value_;
}
constexpr
explicit
operator this_type const &() const &
{
assert(sizeof...(rest) == which());
return head_.value_;
}
constexpr
explicit
operator this_type &&() &&
{
assert(sizeof...(rest) == which());
return std::move(head_.value_);
}
constexpr
explicit
operator this_type const &&() const &&
{
assert(sizeof...(rest) == which());
return std::move(head_.value_);
}
template< typename type >
constexpr
explicit
operator type &() &
{
return static_cast< type & >(tail_);
}
template< typename type >
constexpr
explicit
operator type const &() const &
{
return static_cast< type const & >(tail_);
}
template< typename type >
constexpr
explicit
operator type &&() &&
{
//return static_cast< type && >(std::move(tail_)); // There is known clang++ bug #19917 for static_cast to rvalue reference.
return static_cast< type && >(static_cast< type & >(tail_)); // workaround
}
template< typename type >
constexpr
explicit
operator type const &&() const &&
{
//return static_cast< type const && >(std::move(tail_));
return static_cast< type const && >(static_cast< type const & >(tail_));
}
~U()
{
if (which() == sizeof...(rest)) {
head_.~head();
} else {
tail_.~tail();
}
}
};
// main.cpp
#include <cstdlib>
int
main()
{
U< int, double > u{1.0};
assert(static_cast<double>(u) == 1.0);
u = 0.0;
assert(static_cast<double>(u) == 0.0);
U< int, double > w{1};
assert(static_cast<int>(w) == 1);
return EXIT_SUCCESS;
}
वर्ग U
एक शाब्दिक प्रकार बनाने के लिए इस उदाहरण में यह U
वर्ग (V
) के रूप में लगभग एक ही परिभाषित करना संभव है (first, rest...
के मामले में सभी तुच्छता से destructible कर रहे हैं), लेकिन एक नाशक की परिभाषा के बिना ~U
(यानी शाब्दिक प्रकार है यदि सभी अवरोही प्रकार अक्षर हैं)। फिर टेम्पलेट प्रकार उर्फ
template< typename ...types >
using W = std::conditional_t< (std::is_trivially_destructible<types>{} && ...), V<types...>, U<types...> >;
को परिभाषित करने और U
और V
दोनों में using tail = W<rest...>;
को फिर से परिभाषित। इसलिए, दो लगभग समान वर्ग हैं, केवल विनाशक की उपस्थिति में भिन्न हैं। ऊपर दृष्टिकोण के लिए कोड की अत्यधिक डुप्लिकेशन की आवश्यकता है।
समस्या समस्या को कॉपी/चालित करने योग्य प्रकारों और operator =
और std::is_trivially_copyable
होने के लिए अन्य सभी शर्तों के साथ भी चिंतित है। 5 स्थितियां को लागू करने के लिए पूरी तरह से 2^5 संयोजन प्रदान करती हैं।
वहाँ तकनीक (और कम वर्बोज़, तो ऊपर वर्णित) का उपयोग करने के लिए उपस्थित सी ++ मैं याद आती है, या हो सकता है जल्द आ प्रस्ताव में व्यक्त किसी भी तैयार है?
विनाशक को constexpr
के रूप में चिह्नित करने के लिए एक और विचारशील दृष्टिकोण (भाषा सुविधा) है और यह जांचने के लिए संकलक को प्रदान करता है कि शरीर तत्काल के दौरान तुच्छ एक के बराबर है या नहीं।
अद्यतन:
कोड सरलीकृत के रूप में टिप्पणी में कहा: union
union
तरह वर्ग बन गया। हटाए गए noexcept
विनिर्देशक।
मैं परिदृश्य जो नाशक की इस तरह की डिजाइन करने के लिए ले जा सकता है नहीं जानता। मैं यह भी महसूस करता हूं कि जो कुछ भी परिदृश्य है, जिसे आरएआईआई के उचित उपयोग के साथ हल किया जा सकता है (टेम्पलेट तर्कों के प्रकारों द्वारा लागू ... ')। – Nawaz
मुझे नहीं लगता कि आप मूल्यों को संग्रहीत करने और सीधे विनाश का प्रबंधन करने के लिए 'X' क्यों चाहते हैं/क्यों चाहते हैं। शायद 'std :: is_trivially_destructible' मान पर एक सदस्य या आधार टेम्पलेट किया गया है, तो आप वांछित विनाश को पूर्ववत करने के लिए 'Member_Or_Base'' विनाशक का विशेषज्ञ कर सकते हैं। और पोस्ट करने के लिए यह बहुत अधिक कोड है - जब आपके पास कोई विशिष्ट समस्या होती है तो इसे कम से कम कोड बनाते हैं। –
@ नवाज परिदृश्य तब उठता है जब हमें * सशर्त रूप से शाब्दिक * कक्षा को परिभाषित करने की आवश्यकता होती है।मैं पूरा उदाहरण और एक संभावित दोषपूर्ण समाधान प्रदान करता हूं। – Orient