2011-11-25 22 views
6

मुझे सही अग्रेषण के साथ कुछ कठिनाइयों हैं।बिल्कुल सही अग्रेषण और std :: tuple (या अन्य templated कक्षा)

यहां मेरी समझ का वर्तमान स्तर है: गोंद टेम्पलेट + रावल्यू संदर्भ + std :: आगे और एक विशेष जादुई मोड सक्रिय हो जाता है जहां टेम्पलेट कटौती नियम सामान्य रूप से समान अर्थ नहीं होते हैं, लेकिन पूर्ण अग्रेषण की अनुमति देने के लिए तैयार किए जाते हैं। उदाहरण:

template <typename T> 
void outer(T&& t) 
{ 
    inner(std::forward<T>(t)); // perfect forwarding activated 
} 

लेकिन क्या होगा अगर टी वास्तव में एक टेम्प्लेटेड वर्ग है? उदाहरण के लिए, मैं std :: tuple को कैसे पूर्ण कर सकता हूं? यदि टी & & का उपयोग करते हैं तो मैं टुपल में मौजूद वस्तुओं की सभी प्रकार की जानकारी खो दूंगा।
निम्नलिखित कोड काम हालांकि नहीं कर सकते:

template <typename... Args> 
void outer(std::tuple<Args...>&& t) 
{ 
    inner(std::forward<std::tuple<Args...>>(t)); 
    use_args_types_for_something_else<Args...>(); // I need to have Args available 
} 

int main() 
{ 
    std::tuple<int, double, float> t(4, 5.0, 4.0f); 
    outer(t); 
} 

अंतिम जीसीसी स्नैपशॉट का कहना है:

error: cannot bind 'std::tuple<int, double, float> lvalue to 
std::tuple<int, double, float>&& 

तो स्पष्ट रूप से, हम सामान्य, गैर टेम्पलेट मामले में अभी भी कर रहे हैं जहां lvalue बाँध नहीं कर सकते संदर्भ के लिए rvalue। "परफेक्ट forwading मोड" सक्रिय नहीं है

तो मैं डरपोक हो सकता है और एक टेम्पलेट टेम्पलेट के रूप में मेरी टपल पास करने का प्रयास:

template < 
    typename... Args 
    template <typename...> class T 
> 
void outer(T<Args...>&& t) 
{ 
    inner(std::forward<T<Args...>>(t)); 
    use_args_type_for_something_else<Args...>(); 
} 

लेकिन मैं अभी भी एक ही त्रुटि मिलती है।

+0

क्या आप टाइप को निर्दिष्ट किए बिना std :: आगे कॉल नहीं कर सकते हैं (क्योंकि यह टेम्पलेट फ़ंक्शन है और कटौती का उपयोग कर सकता है)? 'std :: आगे (टी)' – SoapBox

उत्तर

3

बिल्कुल सही अग्रेषण केवल तभी कारगर साबित पैरामीटर के प्रकार के समारोह के लिए एक टेम्पलेट प्रकार है, इसलिए सही अग्रेषण को प्राप्त करने के लिए एक ही रास्ता अपना पहला उदाहरण की तरह है:

template <typename T> 
void outer(T&& t) 
{ 
    inner(std::forward<T>(t)); // perfect forwarding activated 
} 

ऊपर काम करता है क्योंकि यह है एक विशेष मामला जहां TSomeType& या SomeType&& के रूप में घटाया जाता है।

हालांकि, इसका मतलब यह नहीं है कि ट्यूपल तत्वों के लिए प्रकार की जानकारी अच्छी तरह से खो जाती है। यह अभी भी पुनर्प्राप्त करने योग्य है (हालांकि मुझे नहीं लगता कि आप एक विविध टेम्पलेट पैक टाइप कर सकते हैं)। उदाहरण के लिए, यदि आप अभी भी इस तरह use_args_types_for_something_else कॉल कर सकते हैं:

template <class T> 
struct call_uses_args; 

template <class ...Args> 
struct call_uses_args<std::tuple<Args...>> 
{ 
    void call() const { use_args_types_for_something_else<Args...>(); } 
}; 

template <typename TupleT> 
void outer(TupleT&& t) 
{ 
    inner(std::forward<TupleT>(t)); 
    call_uses_args<typename std::remove_reference<TupleT>::type>().call(); 
} 

कोई अच्छा सामान्य समाधान है, हालांकि हो सकता है, लेकिन उम्मीद है कि ऐसी स्थितियों दुर्लभ हैं। (उदा।, इस विशेष उदाहरण में, outer को ओवरलोड करने के लिए यह आसान हो सकता है।)

+0

आपके अच्छे और सटीक उत्तर के लिए धन्यवाद। तो सी ++ 11 में सही अग्रेषण के संबंध में, मुझे अभी भी थोड़ा परेशान लगता है कि यह इस अजीब कॉम्बो "टेम्पलेट + आरआरएफ + एसडीडी :: फॉरवर्ड" पर बहुत निर्भर है। यह एक छोटा सा स्थान बनाता है जहां सामान्य नियम (जैसे "रैवल्यू संदर्भ केवल रावल्यू से बांधते हैं") अब लागू नहीं होते हैं। मुझे आश्चर्य है कि सही अग्रेषण के लिए कुछ विशेष वाक्यविन्यास सी ++ 11 के लिए बेहतर नहीं होगा। वैसे भी, यह सच है कि इस मामले में एक कार्यवाही एक सौदा का बड़ा नहीं है क्योंकि 'बाहरी' के लिए दो अधिभार बनाना, एक कॉन्स रेफरी वाला एक और पीएफ अनुकरण करने के लिए आरएफई के साथ एक बनाना संभव है। –

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