Same_as अवधारणा दो बार टाइप समानता की जाँच क्यों करती है?


19

Https://en.cppreference.com/w/cpp/concepts/same_as पर समान_स अवधारणा के संभावित कार्यान्वयन को देखते हुए मैंने देखा कि कुछ अजीब हो रहा है।

namespace detail {
    template< class T, class U >
    concept SameHelper = std::is_same_v<T, U>;
}

template< class T, class U >
concept same_as = detail::SameHelper<T, U> && detail::SameHelper<U, T>;

पहला सवाल यह है कि एक SameHelperअवधारणा को क्यों किया जाता है? दूसरा कारण है कि same_asजांच करता है कि Tरूप में ही है Uऔर Uउसी के रूप में T? क्या यह बेमानी नहीं है?


सिर्फ इसलिए SameHelper<T, U>कि सच हो सकता है इसका मतलब यह नहीं SameHelper<U, T>हो सकता है।
कुछ प्रोग्रामर ने

1
यह बात है, अगर बराबर बी, बी बराबर नहीं है?
user7769147 17

@ user7769147 हां, और यह उस संबंध को परिभाषित कर रहा है।
फ्राँस्वा एंड्रीक्स

4
हम्म डॉक्यूमेंटिंग के लिए std :: is_same यहां तक ​​कि " कम्यूटेशन संतुष्ट है, अर्थात किसी भी दो प्रकारों के लिए T और U, is_same<T, U>::value == trueif और if if is_same<U, T>::value == true।" इसका मतलब है कि यह डबल चेक आवश्यक नहीं है
केविन

1
नहीं, यह गलत है, std :: is_same कहता है: यदि और केवल यदि शर्त रखी जाती है, तो दो प्रकार सराहनीय हैं। ऐसा जरूरी नहीं है। लेकिन मैं दो गैर-कम्यूटेटिव प्रकारों का उदाहरण खोजने में विफल रहा।
नेमंजा बोरिक

जवाबों:


16

दिलचस्प सवाल। मैंने हाल ही में एंड्रयू सटन की बातचीत को कॉन्सेप्ट पर देखा है, और प्रश्नोत्तर सत्र में किसी ने निम्नलिखित प्रश्न पूछा है: (निम्न लिंक में टाइमस्टैम्प): CppCon 2018: एंड्रयू सटन "60 में अवधारणाएं: सब कुछ आपको जानना चाहिए और कुछ भी नहीं जिसे आप नहीं चाहते"

इसलिए यह सवाल उबलता है: If I have a concept that says A && B && C, another says C && B && A, would those be equivalent?एंड्रयू ने हां में उत्तर दिया, लेकिन इस तथ्य को इंगित किया कि संकलक में कुछ आंतरिक विधियां (जो उपयोगकर्ता के लिए पारदर्शी हैं) अवधारणाओं को परमाणु तार्किक प्रस्तावों में व्याख्यायित करना है ( atomic constraintsजैसा कि एंड्रयू ने इस शब्द को कहा है) और जांचें कि क्या वे हैं बराबर।

अब देखो क्या cppreference के बारे में कहते हैं std::same_as:

std::same_as<T, U>सदस्यता std::same_as<U, T>और इसके विपरीत।

यह मूल रूप से "इफ-एंड-ओनली-इफ" रिश्ता है: वे एक-दूसरे को प्रभावित करते हैं। (तार्किक समानता)

मेरा अनुमान है कि यहाँ परमाणु अड़चनें हैं std::is_same_v<T, U>। जिस तरह से संकलक व्यवहार करते हैं वे std::is_same_vउन्हें सोच सकते हैं std::is_same_v<T, U>और std::is_same_v<U, T>दो अलग-अलग बाधाओं के रूप में (वे अलग-अलग संस्थाएं हैं!)। इसलिए यदि आप std::same_asउनमें से केवल एक का उपयोग करके लागू करते हैं:

template< class T, class U >
concept same_as = detail::SameHelper<T, U>;

तब std::same_as<T, U>और std::same_as<U, T>विभिन्न परमाणु अवरोधों के लिए "विस्फोट" होगा और समतुल्य नहीं बनेंगे।

खैर, संकलक देखभाल क्यों करता है?

इस उदाहरण पर विचार करें :

#include <type_traits>
#include <iostream>
#include <concepts>

template< class T, class U >
concept SameHelper = std::is_same_v<T, U>;

template< class T, class U >
concept my_same_as = SameHelper<T, U>;

// template< class T, class U >
// concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;

template< class T, class U> requires my_same_as<U, T>
void foo(T a, U b) {
    std::cout << "Not integral" << std::endl;
}

template< class T, class U> requires (my_same_as<T, U> && std::integral<T>)
void foo(T a, U b) {
    std::cout << "Integral" << std::endl;
}

int main() {
    foo(1, 2);
    return 0;
}

आदर्श रूप से, my_same_as<T, U> && std::integral<T>उपसमूह my_same_as<U, T>; इसलिए, कंपाइलर को दूसरे टेम्प्लेट स्पेशलाइजेशन का चयन करना चाहिए, इसके अलावा ... ऐसा नहीं है: कंपाइलर एक त्रुटि का उत्सर्जन करता है error: call of overloaded 'foo(int, int)' is ambiguous

इसके पीछे कारण यह है कि चूंकि my_same_as<U, T>और my_same_as<T, U>एक-दूसरे को सब्सक्राइब नहीं करते हैं, my_same_as<T, U> && std::integral<T>और my_same_as<U, T>अतुलनीय हो जाते हैं (सब्सक्राइब के संबंध में बाधाओं के आंशिक रूप से आदेशित सेट पर)।

हालाँकि, यदि आप प्रतिस्थापित करते हैं

template< class T, class U >
concept my_same_as = SameHelper<T, U>;

साथ में

template< class T, class U >
concept my_same_as = SameHelper<T, U> && SameHelper<U, T>;

कोड संकलित करता है।


same_as <T, U> और same_as <U, T> भी अलग-अलग परमाणु संदर्भ हो सकते हैं लेकिन उनका परिणाम अभी भी समान होगा। कंपाइलर समान_स को दो अलग-अलग परमाणु बाधाओं को परिभाषित करने के बारे में क्यों परवाह करता है जो एक तार्किक दृष्टिकोण से समान हैं?
1577 पर user7769147

2
कंपाइलर को किसी भी दो भावों पर संयम निर्वाह के लिए अलग-अलग विचार करने की आवश्यकता होती है , लेकिन यह स्पष्ट रूप से उनके लिए तर्क पर विचार कर सकता है । इसलिए न केवल हमें दोनों दिशाओं की आवश्यकता है (ताकि यह कोई फर्क नहीं पड़ता कि किस क्रम में वे बाधाओं की तुलना करते समय नामित किए गए हैं), हमें भी इसकी आवश्यकता है : यह एक ही अभिव्यक्ति से व्युत्पन्न के दो उपयोग करता है । SameHelperis_same_v
डेविस हेरिंग 20

@ user7769147 अद्यतन जवाब देखें।
रीन काएनबायो 20

1
ऐसा लगता है कि पारंपरिक ज्ञान अवधारणा समानता के बारे में गलत है। टेम्पलेट्स जहां विपरीत is_same<T, U>के समान है is_same<U, T>, दो परमाणु की कमी समान नहीं माना जाता है जब तक कि वे भी एक ही अभिव्यक्ति से गठित कर रहे हैं। इसलिए दोनों की जरूरत है।
एंडीजी

किस बारे में are_same_as? template<typename T, typename U0, typename... Un> concept are_same_as = SameAs<T, U0> && (SameAs<T, Un> && ...);कुछ मामलों में विफल होगा। उदाहरण के लिए, लेकिन इसके are_same_as<T, U, int>बराबर are_same_as<T, int, U>नहीं होगाare_same_as<U, T, int>
user7769147

2

std::is_same सच के रूप में परिभाषित किया गया है अगर और केवल अगर:

T और U समान cv-योग्यता के साथ एक ही प्रकार का नाम देते हैं

जहाँ तक मुझे पता है, मानक "एक ही प्रकार" के अर्थ को परिभाषित नहीं करता है, लेकिन प्राकृतिक भाषा और तर्क में "समान" एक समतुल्य संबंध है और इस प्रकार यह सराहनीय है।

इस धारणा को देखते हुए, जिसे मैं बताता हूं, is_same_v<T, U> && is_same_v<U, V>वास्तव में बेमानी होगी। लेकिन के same_­asसंदर्भ में निर्दिष्ट नहीं है is_same_v; यह केवल प्रदर्शनी के लिए है।

दोनों के लिए स्पष्ट जांच कार्यान्वयन के लिए कम्यूटेटिव होने के बिना same-as-implसंतुष्ट करने की अनुमति देती है same_­as। इसे इस तरह से निर्दिष्ट करना वास्तव में वर्णन करता है कि कैसे अवधारणा को प्रतिबंधित किए बिना व्यवहार किया जाता है कि इसे कैसे लागू किया जा सकता है।

वास्तव में इस दृष्टिकोण को निर्दिष्ट करने के बजाय क्यों चुना गया is_same_v, मुझे नहीं पता। चुने हुए दृष्टिकोण का एक फायदा यकीनन यह है कि दो परिभाषाएं एक-दूसरे से जुड़ी हुई हैं। एक दूसरे पर निर्भर नहीं है।


2
मैं आपसे सहमत हूं, लेकिन यह आखिरी तर्क थोड़ा खिंचाव का है। मेरे लिए, ऐसा लगता है: "अरे, मेरे पास यह पुन: प्रयोज्य घटक है जो मुझे बताता है कि क्या दो प्रकार समान हैं। अब मेरे पास यह अन्य घटक है जो यह जानने की जरूरत है कि क्या प्रकार समान हैं, लेकिन, मेरे पिछले घटक का पुन: उपयोग करने के बजाय , मैं सिर्फ इस मामले के लिए एक तदर्थ समाधान बनाऊंगा। अब मैंने उस आदमी को 'डिकॉउड' कर दिया है, जिसे समानता की परिभाषा वाले व्यक्ति से समानता की परिभाषा की आवश्यकता है। याय! "
कैसियो रेनन

1
@ CássioRenan ज़रूर। जैसा मैंने कहा, मुझे नहीं पता कि, यह सबसे अच्छा तर्क है कि मैं साथ आ सकता हूं। लेखकों के पास बेहतर तर्क हो सकता है।
एरोरिका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.