2017-02-23 10 views
6

से टेम्पलेट तर्क कटौती मैं वर्तमान में इस बारे में सोच रहा हूं कि std::sting के साथ-साथ स्ट्रिंग अक्षर के लिए सामान्य प्रकार के टेम्पलेट को कैसे बाध्य किया जाए। इसलिए मैं std::is_same का उपयोग करके वांछित प्रकार के साथ अनुमानित प्रकार की तुलना करता हूं। std::string के मामले में यह तुरंत काम करता है। स्ट्रिंग अक्षर के लिए, एक char const array का अर्थ है, यह केवल तभी काम करता है जब मैं std::decay प्रकार पर उपयोग करता हूं और फिर परिणाम char const * पर परिणाम की तुलना करता हूं। यदि मैं सीधे टाइप किए गए प्रकार की तुलना करता हूं जो मुझे लगता है कि यह होना चाहिए, is_same झूठा रिटर्न देता है, जैसा कि निम्न उदाहरण कोड द्वारा दिखाया गया है।स्ट्रिंग लिटल

char const [5] : char const [5] 
0 
char const * __ptr64 : char const * __ptr64 
1 

अब, क्यों is_same रिटर्न पहले मामले में झूठी भले ही प्रकार के समान दिखाई देते हैं कि मैं क्या सोच रहा हूं:

template <class TYPE> 
void function(TYPE&& parameter) 
{ 
    //this doesn't work as expected 
    std::cout << typeid(TYPE).name() << " : " << typeid(char const [5]).name() << std::endl; 
    std::cout << std::is_same<char const [5], TYPE>::value << std::endl; 
    //this works as expected 
    std::cout << typeid(std::decay_t<TYPE>).name() << " : " << typeid(char const *).name() << std::endl; 
    std::cout << std::is_same<char const *, std::decay_t<TYPE>>::value << std::endl; 
} 

int main(int argc, char** argv) 
{ 
    function("name"); 
    return 0; 
} 

उत्पादन उत्पन्न निम्नलिखित है।

केवल संभावित व्याख्या यह है कि मैं के साथ आ सकता है कि समारोह std::is_same भीतर std::decay के लिए इसी तरह एक परिवर्तन प्रकार (उदाहरण के लिए एक समारोह कॉल) को लागू किया जाता है। लेकिन फिर फिर से यह परिवर्तन अन्य प्रकार के साथ भी होगा, जो एक ही परिणाम प्रदान करेगा और इसके परिणामस्वरूप समानता होगी।

+0

सी ++ 17 तक प्रतीक्षा करें, और 'std :: string_view' का उपयोग करने के लिए अपना टेम्पलेट लिखें। –

+1

'TYPE' से संदर्भों को हटाने का प्रयास करें। स्ट्रिंग अक्षर हैं lvalues। –

+0

धन्यवाद, आप सही थे। मुझे यह नहीं पता था। लाइन को 'std :: is_same > :: वैल्यू के परिणाम समानता में बदल रहा है। स्ट्रिंग अक्षर को लालसा क्यों माना जाता है? अगर यह एक शाब्दिक था तो इसे एक रावल माना जाएगा, है ना? और क्या हम इसे स्वीकार कर सकते हैं? – user1488118

उत्तर

6

स्ट्रिंग शाब्दिक char const [N] के रूप में मूल्य द्वारा पारित नहीं कर रहे हैं, लेकिन char const (&)[N] रूप संदर्भ द्वारा।

यह मेरे लिए सही ढंग से काम करता है:

std::cout << std::is_same<char const (&)[5], TYPE>::value << std::endl; 

नोट here कि

1) एक std::type_info ऑब्जेक्ट प्रकार प्रकार का प्रतिनिधित्व करने के लिए संदर्भित करता है। यदि प्रकार एक संदर्भ प्रकार है, तो परिणाम संदर्भित का प्रतिनिधित्व करने वाले std::type_info ऑब्जेक्ट को संदर्भित करता है।

आप आसानी से सत्यापित कर सकते हैं कि is_same की जाँच करके type_info के रूप में एक ही तरह से संदर्भ सत्ता त्यागने नहीं है, उदाहरण के लिए कि

std::is_same<int&, int>::value == false 

यही कारण है typeid नाम ही है, लेकिन अपने is_same परीक्षण अभी भी विफल रहता है।

2

जीसीसी कस्टम फ़ंक्शन का उपयोग करना:

template < class T > 
constexpr std::string type_name() 
{ 
    std::string p = __PRETTY_FUNCTION__; 
    return p.substr(43 + 10, p.length() - 100 - 1 - 10); 
} 

और अपने कोड में जोड़ने:

std::cout << type_name<TYPE>() << " : " << type_name<char const [5]>() << std::endl; 

परिणाम हैं:

A5_c : A5_c 
0 
const char (&)[5] : const char [5] 

तो तुम TYPE पर std::remove_reference उपयोग करने के लिए की जरूरत है।

+0

मुझे लगता है कि आप प्रभाव से संबंधित हैं। हालांकि, टिप्पणियों में केरेक एसबी द्वारा इसका कारण उल्लेख किया गया था: स्ट्रिंग अक्षर स्पष्ट रूप से लालसा हैं, न कि राजस्व। इसलिए अग्रेषण संदर्भ पैरामीटर के माध्यम से पारित होने पर 'टी' के बजाय 'टी'' के रूप में टाइप को घटाया जाता है। – user1488118

+0

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

0

यह कंपाइलर की गलती हो सकती है। कंपाइलर संकलित समय पर टाइपिड द्वारा दिए गए ऐसे प्रकार-ऑब्जेक्ट उत्पन्न करता है। संकलक प्रत्येक लंबाई (0 से 2 ** एन) के लिए सरणी प्रकारों को संकलित नहीं करेगा, इसलिए जब आवश्यक हो तो यह उन्हें संकलित करता है, और यह डुप्लिकेट के बारे में "भूल" सकता है। एक विशेष टेम्पलेट का उपयोग करने का प्रयास करें जहां आप निहित प्रकार से लंबाई को अलग करते हैं। यह प्रकार नहीं है लेकिन आप जांच सकते हैं कि यह दूसरे के बराबर है या नहीं।

template<class T, size_t size> 
struct array_t{}; 

    template <class T, size_t size> 
void function(T[size] parameter) { 
    std::cout << typeid(array_t<T, size>).name() << " : " << typeid(array_t<char, 5>).name() << std::endl; 
    std::cout << std::is_same<array_t<T, size>, array_t<char, 5>>::value << std::endl; 
}; 
संबंधित मुद्दे