2011-11-25 18 views
10

मैं एक भिन्न टेम्पलेट का उपयोग कर रहा हूं जो सी और सी ++ के बीच इंटरफ़ेस में अपवाद फ़ायरवॉल के रूप में कार्य करता है। टेम्पलेट बस एक फ़ंक्शन लेता है, उसके बाद एन तर्क होता है और फ़ंक्शन कैच ब्लॉक के अंदर फ़ंक्शन को कॉल करता है। यह ठीक काम कर रहा है, दुर्भाग्यवश उन कार्यों में से एक जिन्हें मैं अभी कॉल करना चाहता हूं, एक अतिरिक्त डिफ़ॉल्ट तर्क लेता है। नतीजतन फ़ंक्शन का नाम हल नहीं होता है और टेम्पलेट संकलित करने में विफल रहता है।वैराडिक टेम्पलेट्स, डिफ़ॉल्ट तर्कों के साथ फ़ंक्शंस करने के लिए बिल्कुल सही अग्रेषण

त्रुटि है:

perfect-forward.cpp: In function ‘void FuncCaller(Func, Args&& ...) [with Func = void (*)(const std::basic_string<char>&, double, const std::vector<int>&), Args = {const char (&)[7], double}]’ :
perfect-forward.cpp:69:41: instantiated from here
perfect-forward.cpp:46:4: error: too few arguments to function

कोड का एक सरलीकृत संस्करण है इस प्रकार है:

template< class Func, typename ...Args > 
void FuncCaller(Func f, Args&&... params) 
{ 
    try 
    { 
     cout << __func__ << " called\n"; 
     f(params...); 
    } 
    catch(std::exception& ex) 
    { 
     cout << "Caught exception: " << ex.what() << "\n"; 
    } 
} 

void Callee(const string& arg1, double d, const vector<int>&v = vector<int>{}) 
{ 
    cout << __func__ << " called\n"; 
    cout << "\targ1: " << arg1 << "\n"; 
    cout << "\td: " << d << "\n"; 
    cout << "\tv: "; 
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " " )); 
    cout << "\n"; 
} 

int main() 
{ 
    vector<int> v { 1, 2, 3, 4, 5 }; 

    FuncCaller(Callee, "string", 3.1415, v); 
    FuncCaller(Callee, "string", 3.1415); **// Fails to compile** 

    return 0; 
} 

चाहिए इस कोड को काम या मैं संकलक से बहुत ज्यादा की उम्मीद कर रहा हूँ?

नोट: मैं, कंस्ट्रक्टर्स डिफ़ॉल्ट तर्क है और कोड को संकलित करता है और अपेक्षा के अनुरूप काम करता है कि के साथ पूर्ण अग्रेषण के उपयोग का परीक्षण किया है

अर्थात्:

template<typename TypeToConstruct> struct SharedPtrAllocator 
{ 
    template<typename ...Args> shared_ptr<TypeToConstruct> 
     construct_with_shared_ptr(Args&&... params) { 
     return std::shared_ptr<TypeToConstruct>(new TypeToConstruct(std::forward<Args>(params)...)); 
    }; 
}; 

काम करता है जब 2 के साथ cfollowing निर्माता बुला या 3 तर्क ...

MyClass1(const string& arg1, double d, const vector<int>&v = vector<int>{}) 
+2

(यह 'एफ (std :: आगे (पैराम्स) ...); ', वैसे भी होना चाहिए।) –

उत्तर

8

मुझे नहीं लगता कि यह किसी भी तरह से हासिल किया जा सकता है। डिफ़ॉल्ट तर्क मान फ़ंक्शन हस्ताक्षर का हिस्सा नहीं हैं। जब आप फ़ंक्शन को शाब्दिक रूप से कॉल करते हैं तो वे केवल कोड-जनरेशन शॉर्ट-हैंड हैं जिन्हें कंपाइलर द्वारा विस्तारित किया जाता है। इसी प्रकार, std::bind या तो डिफ़ॉल्ट तर्क नहीं उठाएगा।

+1

मैंने सोचा कि यह उन पंक्तियों में कुछ लंबा था ... ब्याज से बाहर क्यों डिफॉल्ट तर्क के साथ निर्माता काम करते हैं? – mark

+1

ठीक है, आप सीधे फ़ंक्शन को कॉल कर सकते हैं, जो आपका कोड करता है (यदि आप सभी टेम्पलेट पैरामीटर प्रतिस्थापन को अनदेखा करते हैं)। लेकिन मूल प्रश्न में, फ़ंक्शन प्रकार स्वयं ही घटाया जाता है, और यही वह जगह है जहां आप डिफ़ॉल्ट तर्क खो देते हैं। –

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