मैंने एसओ पर यहां पर एक सूत्र का अनुसरण किया कि कैसे एक आउटपुट योग्य विशेषता वर्ग को कार्यान्वित किया जाए ताकि संकलन समय पर जांच की जा सके कि एक प्रकार std::ostream
पर आउटपुट हो सकता है या नहीं। वर्ग का कार्यान्वयन निम्नलिखित है:
template<typename U>
struct OstreamOutputableTrait
{
template<typename T>
static decltype(std::declval<std::ostream&>() << std::declval<T>(), std::true_type{} )
IsOstreamOutputtable(std::ostream& os, const T& var) {}
// for vector<T>
template<typename T>
static std::false_type IsOstreamOutputtable(std::ostream& os, const std::vector<T>& var)
{}
template<typename > static auto IsOstreamOutputtable(...) {
return std::false_type {};
}
static const auto value =
decltype(IsOstreamOutputtable(std::declval<std::ostream&>(), std::declval<U>()))::value;
};
// operator implementation
template<typename Key, typename T>
std::ostream& operatorImpl(std::ostream& os, const std::map<Key,T>& map, const std::true_type& ) {
for(auto it = map.begin(); it!= map.end(); ++it)
os << "(" << (*it).first << " ; " << (*it).second << ")" <<"\n";
return os;
}
template<typename Key, typename T>
std::ostream& operatorImpl(std::ostream& os, const std::map<Key, T>& map, const std::false_type& ) {
os << "\nElements of the map are not printable.\n";
return os;
}
// operator << on <Key, value> maps
template<typename Key, typename T>
std::ostream& operator<<(std::ostream& os, const std::map<Key, T>& map)
{
// redirect using SFINAE to correct Impl of the operator<< : ty always returns true!
auto ty = std::integral_constant<bool,
OstreamOutputableTrait<typename std::decay_t<T> >::value &&
OstreamOutputableTrait<typename std::decay_t<Key> >::value>();
operatorImpl(os, map, ty);
return os;
}
मेरे पास समस्या यह है कि वेरिएबल ty
ऊपर दिए गए फ़ंक्शन में हमेशा std::true_type
देता है। क्या इसका मतलब यह है कि दोनों <Key,T>
std::map
टेम्प्लेट वर्ग के टाइपनाम STL में डिफ़ॉल्ट रूप से std::ostream
पर आउटपुट योग्य हैं? अगर कोई समझा सकता है कि मैं कुछ गलत कहां कर रहा हूं, तो इससे मुझे बहुत मदद मिलेगी।
धन्यवाद अमीन
2 जवाब
आपकी त्रुटि IsOstreamOutputtable()
के विविध संस्करण को घोषित करने में है
template <typename>
static auto IsOstreamOutputtable (...)
{ return std::false_type {}; }
आप इसे एक टेम्पलेट पैरामीटर के साथ टेम्पलेट फ़ंक्शन के रूप में घोषित करते हैं जिसे तर्कों से नहीं निकाला जा सकता है।
इसलिए, जब आप फ़ंक्शन को decltype()
से कॉल करते हैं
static const auto value =
decltype(IsOstreamOutputtable(std::declval<std::ostream&>(), std::declval<U>()))::value;
संकलक विविध संस्करण को ध्यान में नहीं रख सकता है।
समाधान।
(1) आप IsOstreamOutputtable()
को कॉल करने वाले टेम्प्लेट पैरामीटर को स्पष्ट कर सकते हैं
// ..........................VVV explicit template parameter
decltype(IsOstreamOutputtable<U>(std::declval<std::ostream&>(), std::declval<U>()))::value;
तो संकलक विविध संस्करण का उपयोग कर सकता है,
समस्या: यह समाधान std::vector
संस्करण के लिए काम नहीं करता
(2) (बेहतर) आप IsOstreamOutputtable()
के विविध संस्करण को गैर-टेम्पलेट वाला बना सकते हैं
// no needs of template
static auto IsOstreamOutputtable (...)
{ return std::false_type {}; }
ऑफ टॉपिक: IsOstreamOutputtable()
विधियों को केवल decltype()
के अंदर ही बुलाया जाता है, इसलिए परिभाषित करने की कोई आवश्यकता नहीं है, आपको केवल उन्हें घोषित करना है। (और यदि आप उन्हें परिभाषित करते हैं, तो कृपया सुसंगत रहें: std::true_type
लौटने वाली विधि के लिए शरीर खाली नहीं हो सकता)।
पिछला रिटर्न प्रकार, और अन्य छोटे सरलीकरणों का उपयोग करके, आपकी टाइपराइटिंग को थोड़ा कम किया जा सकता है
template <typename U>
struct OstreamOutputableTrait
{
template <typename T>
static auto IsOstreamOutputtable (T const & var)
-> decltype( std::declval<std::ostream&>() << var, std::true_type{} );
// special case for vector<T>
template <typename T>
static std::false_type IsOstreamOutputtable (std::vector<T> const &);
static std::false_type IsOstreamOutputtable (...);
static constexpr auto value
= decltype(IsOstreamOutputtable(std::declval<U>()))::value;
};
@ मैक्स 66,
मेरा विचार था कि:
template<typename T>
static decltype(std::declval<std::ostream&>() << std::declval<T>(), std::true_type{} )
IsOstreamOutputtable(std::ostream& os, const T& var) {}
जाँच करेगा कि प्रत्येक प्रकार T
के लिए जो operator<<
का उपयोग करके आउटपुट किया जा सकता है, decltype std::true_type
का प्रकार लौटाएगा। इस संदर्भ में, विविध अधिभार:
template<typename > static auto IsOstreamOutputtable(...) {
return std::false_type {};
}
भ्रम पैदा करने के अलावा कोई उपयोगिता नहीं है। ऐसा कहकर, अगर मैं वाक्यविन्यास का उपयोग करता हूं:
decltype(IsOstreamOutputtable<U>(std::declval<std::ostream&>(), std::declval<U>()))::value;
क्या वैरिएडिक फ़ंक्शन की प्राथमिकता पहले वाले पर होगी जो std::true_type
लौटाता है?
संबंधित सवाल
नए सवाल
c++
C ++ एक सामान्य-प्रयोजन प्रोग्रामिंग भाषा है। यह मूल रूप से C के विस्तार के रूप में डिज़ाइन किया गया था और इसमें एक समान सिंटैक्स है, लेकिन यह अब पूरी तरह से अलग भाषा है। C ++ कंपाइलर के साथ संकलित कोड के बारे में प्रश्नों के लिए इस टैग का उपयोग करें। विशिष्ट मानक संशोधन [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] या [C ++ 23], आदि से संबंधित प्रश्नों के लिए संस्करण-विशिष्ट टैग का उपयोग करें। ।