2011-10-25 27 views
8

सारांश: मैं एक ऐसे फ़ंक्शन के साथ समाप्त करना चाहता हूं जो सटीक प्रकारों को घटा देता है जिसे इसे कहा जाता है और लेता है (उदाहरण के लिए) एक ट्यूपल जो उन्हें आगे बढ़ाता है (जिनके प्रकार समारोह के साथ बुलाए जाने वाले सटीक प्रकारों से अलग)।मूल प्रकारों के ज्ञान को कम करने, साथ ही

मैं किसी दिए गए फ़ंक्शन में तर्कों के प्रकारों को कटौती के माध्यम से "जानना" करने की कोशिश कर रहा हूं, साथ ही साथ उन्हें अग्रेषित करना। मुझे लगता है कि यह कैसे काम करता है इसके बारे में कुछ महत्वपूर्ण याद आ रही है। int,double,void*,std::string&,const char*और अग्रेषित arugments भी -

#include <tuple> 
#include <string> 
#include <functional> 

template <typename ...Args> 
struct unresolved_linker_to_print_the_type { 
    unresolved_linker_to_print_the_type(); 
}; 

void f(int,double,void*,std::string&,const char*) { 
} 

template <typename F, typename ...Args> 
void g1(F func, Args&&... args) { 
    unresolved_linker_to_print_the_type<Args...>(); 
    auto tuple = std::forward_as_tuple(args...); 
    unresolved_linker_to_print_the_type<decltype(tuple)>(); 
} 

template <typename F, typename T, typename ...Args> 
void g2(F func, const T& tuple, Args... args) { 
    unresolved_linker_to_print_the_type<Args...>(); 
    unresolved_linker_to_print_the_type<decltype(tuple)>(); 
} 

int main() { 
    int i; 
    double d; 
    void *ptr; 
    std::string str; 
    std::string& sref = str; 
    const char *cstr = "HI"; 

    g1(f, i,d,ptr,sref,cstr); 
    g2(f, std::forward_as_tuple(i,d,ptr,sref,cstr), i,d,ptr,sref,cstr); 
} 

मैं देखना चाहते हैं क्या एक परिदृश्य मेरी समारोह (जैसे g1 या g2) कहा जाता हो जाता है जब यह जानता है, जहां और दोनों मूल प्रकार का उपयोग कर सकते है।

इस उदाहरण में मुझे यह जानकारी g1 या g2 के भीतर से नहीं मिल पाती है। (जानबूझकर, प्रकार बाहर मुद्रित करने के लिए) लिंकर त्रुटि मुझे पता चलता g1 में वे हैं:

int&, double&, void*&, std::string&, char const*& 
int&, double&, void*&, std::string&, char const*& 

और g2 में:

int, double, void*, std::string, char const* 
int&, double&, void*&, std::string&, char const*& 

दो बात कर रहे हैं मैं यहाँ नहीं मिलता:

  1. क्यों मुद्रित (लिंकर त्रुटि के माध्यम से) प्रकारों में से कोई भी वास्तव में मेरे द्वारा पारित किए गए मिलान से मेल नहीं खाता है? (int,double,void*,std::string&,const char)। क्या मैं वास्तव में जो पारित किया गया था उसे कम कर सकता हूं? अधिमानतः "प्राकृतिक" वाक्यविन्यास के साथ, यानी सबकुछ सिर्फ एक बार और कुछ भी स्पष्ट रूप से लिखा नहीं गया है। मैं स्पष्ट रूप से लिख सकता हूं:

    g2<decltype(&f),decltype(std::forward_as_tuple(i,d,ptr,sref,cstr)),int,double,void*,std::string&,const char*>(f,std::forward_as_tuple(i,d,ptr,sref,cstr),i,d,ptr,sref,cstr); 
    

    लेकिन कम से कम कहने के लिए यह "अनावश्यक" है!

  2. g1 में समारोह हस्ताक्षर घोषणा में && की उपस्थिति टेम्पलेट पैरामीटर Args अपने आप में प्रकार बदलने के लिए लगता है। की तुलना उस के साथ:

    template <typename T> 
    void test(T t); 
    

    या:

    template <typename T> 
    void test(T& t); 
    

    के साथ उन लोगों में से किसी का उपयोग कर:

    int i; 
    test(i); 
    

    T के प्रकार के परिवर्तन नहीं करता है। &&T के प्रकार को तब क्यों बदलता है जब & नहीं होता है?

+0

पुन: "टीएल; डॉ" - 2p2er? –

+0

आप किस कंपाइलर का उपयोग कर रहे हैं जो विविध टेम्पलेट पैरामीटर का समर्थन करता है? –

+0

@ जॉन डीबलिंग जी ++ 4.7.0, 20111010 ट्रंक संशोधन 17 9 76 9 इसे संकलित किया गया लेकिन लिंक नहीं किया गया (यानी मुझे उम्मीद थी कि मैं लिंकर त्रुटियों में प्रकार देख सकता हूं) – Flexo

उत्तर

2

पहले सवाल का जवाब: कार्यों के लिए

तर्क भाव, नहीं प्रकार हैं। इन दोनों के बीच अंतर अध्याय 5 में व्यक्त किया है [expr], पी 5:

एक अभिव्यक्ति शुरू में टाइप करें "टी के संदर्भ में" (8.3.2, 8.5 है

हैं।3), किसी भी आगे विश्लेषण से पहले टी को समायोजित किया जाता है।

इस प्रकार, g(str) और g(sref) के बीच कभी भी कोई अंतर नहीं है। g() हमेशा std::string देखता है, और कभी भी संदर्भ नहीं देता है।

अतिरिक्त अभिव्यक्तियां lvalue या rvalue हो सकती हैं (वास्तव में यह C++ 11 नियमों का सरलीकरण है, लेकिन यह इस चर्चा के लिए पर्याप्त है - यदि आप विवरण 3.10 [basic.lval] में हैं।)।

दूसरे प्रश्न के उत्तर:

खाका प्रपत्र के मापदंडों:

template <class T> 
void g(T&&); 

विशेष कर रहे हैं।

T&& एक lvalue को बांधता है, T एक lvalue संदर्भ प्रकार के रूप में निष्कर्ष निकाला जाता है, अन्यथा T बिल्कुल सामान्य कटौती नियमानुसार deduces: वे T, T&, या यहाँ तक const T&& निम्नलिखित तरीके से विपरीत हैं।

उदाहरण:, (एक rvalue A)

struct A{}; 

void bar(const A&); 
void bar(A&&); 

template <class T> 
void foo(T&& t) 
{ 
    bar(static_cast<T&&>(t)); // real code would use std::forward<T> here 
} 

एक foo(A()) कॉल करता है सामान्य प्रति T deduces:

int i = 0; 
g(i); // calls g<int&>(i) 
g(0); // calls g<int>(0) 

यह व्यवहार है तो सही अग्रेषण जो आम तौर पर की तरह दिखता है कहा जाता है का समर्थन करने के लिए A के रूप में नियम। foo के अंदर हमने t को A&& (एक रावल्यू) पर डाला और bar पर कॉल किया। bar का ओवरलोड जो तब एक रावल्यू A लेता है, तब चुना जाता है। अर्थात। अगर हम एक रैल्यू के साथ foo पर कॉल करते हैं, तो foobar पर एक रावल्यू के साथ कॉल करता है।

लेकिन अगर हम foo(a) (एक lvalue A) कहते हैं, तो TA& के रूप में deduces। अब लगता है कि कलाकारों:

static_cast<A&>(t); 

यानी:

static_cast<A& &&>(t); 

जो संदर्भ नियम टूट के नीचे करने के लिए सरल lvalue t को एक लवल्यू (नो-ऑप कास्ट) में डाला जाता है, और इस प्रकार bar ओवरलोड लोड करने के लिए ओवरलोड किया जाता है। अर्थात। अगर हम एक लाभा के साथ foo पर कॉल करते हैं, तो foobar को एक लवल के साथ कॉल करता है। और यही वह जगह है जहां सही अग्रेषण शब्द आता है।

+1

तो संक्षेप में इस तथ्य को कम करने का कोई तरीका नहीं है कि 'sref' एक संदर्भ था और' रेफरी 'नहीं था और '&&' स्पष्ट रूप से कटौती का एक विशेष मामला है। – Flexo

+0

वास्तव में अंतर्दृष्टिपूर्ण उत्तर के लिए धन्यवाद - मुझे डर था कि यह मामला हो सकता है, ऐसा लगता है कि मैं योजना बी के साथ जा रहा हूं! – Flexo

+0

धन्यवाद ऑवुडलैंड। वह आप में से उदार था। –

0

प्रकार (यहां तक ​​कि सी ++ में) ज्यादातर एक संकलित प्रकार धारणा (निश्चित रूप से vtables में आरटीटीआई को छोड़कर) हैं।

यदि आपको पूरी तरह गतिशील प्रकार की आवश्यकता है, तो सी ++ उस के लिए सबसे अच्छी भाषा नहीं हो सकती है।

शायद आप जीसीसी (वास्तव में g++ का विस्तार कर सकते हैं, मानते हैं कि यह कम से कम 4 है।6) प्लगइन या GCC MELT एक्सटेंशन (एमईएलटी जीसीसी का विस्तार करने के लिए एक उच्च स्तरीय डोमेन विशिष्ट भाषा है) जो आप चाहते हैं (उदाहरण के लिए एक अतिरिक्त बिल्टिन प्रदान करना जो कुछ निरंतर स्ट्रिंग आदि में अपने तर्कों के प्रकार को एन्कोड करता है। ...), लेकिन इसके लिए कुछ काम की आवश्यकता होती है (और जीसीसी के लिए विशिष्ट है)।

लेकिन मुझे समझ में नहीं आता कि आप सी में ऐसी बार्को चीजें क्यों करना चाहते हैं। यदि गतिशील टाइपिंग आपके लिए बहुत महत्वपूर्ण है, तो आप गतिशील रूप से टाइप की गई भाषा का उपयोग क्यों नहीं करते ??

+0

मैं सी ++ में गतिशील टाइपिंग नहीं करना चाहता, मैं स्थिर टाइपिंग करना चाहता हूं, लेकिन संकलन में उन प्रकारों के बारे में अधिक जानकारी प्राप्त करना चाहता हूं वर्तमान में मुझे पता है कि समय कैसे। – Flexo