9

मैं एक फ़ंक्शन टेम्पलेट का विशेषज्ञ कैसे करूं जो सार्वभौमिक संदर्भ पैरामीटर लेता है?एक फ़ंक्शन टेम्पलेट को विशेषज्ञता देना जो सार्वभौमिक संदर्भ पैरामीटर लेता है

foo.hpp:

template<typename T> 
void foo(T && t) // universal reference parameter 

foo.cpp

template<> 
void foo<Class>(Class && class) { 
    // do something complicated 
} 

यहाँ, Class अब एक deduced प्रकार है और इस तरह वास्तव में Class है; यह संभवतः Class & नहीं हो सकता है, इसलिए संदर्भ ढहने वाले नियम मुझे यहां मदद नहीं करेंगे। मैं शायद एक और विशेषज्ञता बना सकता हूं जो Class & पैरामीटर (मुझे यकीन नहीं है) लेता है, लेकिन इसका मतलब यह है कि foo के भीतर सभी पैरामीटर के लिए रावल/लवल्यू संदर्भों के हर संभव संयोजन के लिए मौजूद सभी कोड डुप्लिकेट करना, जो सार्वभौमिक संदर्भ माना जाता है बचने के लिए।

क्या इसे पूरा करने का कोई तरीका है?

मामले में मेरी समस्या के बारे में विशिष्ट वहाँ इसे हल करने के लिए एक बेहतर तरीका है होने के लिए:

मैं एक प्रोग्राम है जो कई खेल सर्वर से कनेक्ट कर सकते हैं, और प्रत्येक सर्वर, अधिकांश भाग के लिए, द्वारा सब कुछ कहता है वही नाम। हालांकि, उनके पास कुछ चीजों के लिए थोड़ा अलग संस्करण हैं। कुछ अलग-अलग श्रेणियां हैं जो ये चीजें हो सकती हैं: एक चाल, एक वस्तु, आदि। मैंने आंतरिक कोड के कॉल के लिए कार्यों के सेट "एनम को स्थानांतरित करने के लिए कदम स्ट्रिंग" का एक सामान्य प्रकार लिखा है, और मेरा सर्वर इंटरफ़ेस कोड समान है कार्य करता है। हालांकि, कुछ सर्वरों की अपनी आंतरिक आईडी होती है जो वे संवाद करते हैं, कुछ स्ट्रिंग का उपयोग करते हैं, और कुछ अलग-अलग स्थितियों में दोनों का उपयोग करते हैं।

अब मैं जो करना चाहता हूं वह इसे थोड़ा और सामान्य बना देता है।

मैं ServerNamespace::server_cast<Destination>(source) जैसे कुछ कॉल करने में सक्षम होना चाहता हूं। इससे मुझे Move से std::string या ServerMoveID पर कास्ट करने की अनुमति मिल जाएगी। आंतरिक रूप से, मुझे एक प्रतिलिपि बनाने की आवश्यकता हो सकती है (या इससे आगे बढ़ना) क्योंकि कुछ सर्वरों को यह आवश्यक है कि मैं भेजे गए संदेशों का इतिहास रखूं। सार्वभौमिक संदर्भ इस समस्या का स्पष्ट समाधान प्रतीत होते हैं।

हेडर फाइल मैं अभी सोच रहा हूँ बस इस का पर्दाफाश होगा:

namespace ServerNamespace { 

template<typename Destination, typename Source> 
Destination server_cast(Source && source); 

} 

और कार्यान्वयन फ़ाइल टेम्पलेट विशेषज्ञताओं के रूप में सभी कानूनी रूपांतरण को परिभाषित करेगा।

struct foo { 
    struct tag {}; 
}; 

struct bar { 
    struct tag {}; 
}; 

template<typename Destination, typename Source> 
Destination server_cast(Source && source, foo::tag) { 
    // foo 
} 

template<typename Destination, typename Source> 
Destination server_cast(Source && source, bar::tag) { 
    // bar 
} 

template<typename Destination, typename Source> 
Destination server_cast(Source && source) { 
    return server_cast<Destination>(std::forward<Source>(source), typename std::remove_reference<Source>::type::tag()); 
} 
+1

क्या 'f' होना चाहिए 'foo'? इसके अलावा, समस्या का संदर्भ क्या है? आप आम तौर पर ओवरलोड लोड करना चाहते हैं, विशेषज्ञ नहीं। – GManNickG

+0

@GManNickG शायद मैंने गलत शब्दावली का उपयोग किया था।मैंने –

+0

को पूरा करने की कोशिश कर रहा हूं, इस मुद्दे पर वास्तव में एक अच्छा लेखन करने के लिए मैंने अपने प्रश्न को और विस्तार से संपादित किया है, देखें: https://mortoray.com/2013/06/03/overriding-the-broken-universal-reference -टी/ –

उत्तर

2

मेरी राय में सबसे अच्छा समाधान है जहाँ आप के बजाय वास्तविक प्रकार की तुलना में टैग पर ओवरलोड एक टैग प्रेषण प्रणाली का उपयोग करने के लिए है।

template< class X > struct Whatever { 
    void f(){ ... } 
}; 

template<> struct Whatever<UserType> { 
    void f(){ ... } 
}; 

कारण मैं कहता हूँ यह सबसे विस्तृत है, क्योंकि आप एक विशेषज्ञता कहीं भी जोड़ सकते हैं अंदर या फ़ाइल है कि जो कुछ भी परिभाषित करता है बाहर, है।

यह पब्बी द्वारा सुझाए गए टैग प्रेषण समाधान के लिए अनन्य, विशेष नहीं है।

+0

मुझे इसके बारे में और कुछ सोचना होगा। –

1

ऐसा करने का सबसे विस्तृत बात एक टेम्पलेट वर्ग विशेषज्ञता बनाने के लिए है:

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