2016-08-28 8 views
5

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

template<typename F> 
struct function_traits; 

template<typename T, typename R, typename... Args> 
struct function_traits<R(T::*)(Args...) const> { 
    using return_type = R; 
    using param_types = std::tuple<Args...>; 
}; 

template<typename T> struct function_traits : public 
function_traits<decltype(&T::operator())> {}; 

template <typename T> 
T* get_arg(int id) 
{ 
    // Actual implementation omitted. Uses the id parameter to 
    // do a lookup into a table and return an existing instance 
    // of type T. 
    return new T(); 
} 

template <typename Func> 
void call_func(Func&& func, int id) 
{ 
    using param_types = function_traits<Func>::param_types>; 

    func(*get_arg<param_types>(id)...); // <--- Problem is this line 
} 

call_func([](int& a, char& b) { }, 3); 

समस्या यह है कि वास्तव में func(*get_arg<param_types>(id)...); param_types के बाद से संकलन नहीं करता है एक टपल और नहीं एक पैरामीटर पैक है। संकलक इस त्रुटि को उत्पन्न करता है: "विस्तृत करने के लिए कोई पैरामीटर पैक उपलब्ध नहीं है"।

func(*get_arg<int>(id), *get_arg<char>(id)); 

और तर्कों के किसी भी संख्या के लिए है कि काम हैं: जैसे लाइन का विस्तार करने के लिए मैं क्या हुआ है पसंद आया होगा। क्या परिणाम प्राप्त करने का कोई तरीका है?

यह प्रश्न समान लगता है लेकिन मेरी समस्या को स्वयं हल नहीं करता है: "unpacking" a tuple to call a matching function pointer। मेरे पास एक प्रकार की सूची है और उस से मैं फ़ंक्शन तर्क के रूप में उपयोग करने के लिए मानों की एक सूची उत्पन्न करना चाहता हूं। अगर मेरे पास मूल्यों की सूची थी तो मैं उन्हें विस्तारित कर सकता हूं और उस प्रश्न में उल्लिखित कार्य को कॉल कर सकता हूं, लेकिन मैं नहीं करता हूं।

+0

'call_func' के अंदर' func' पर कॉल का अपेक्षित परिणाम क्या है? कि सभी तर्क 'आईडी' के बराबर होना चाहिए? आपके उदाहरण में 'call_func ([] (int & a, char & b) {}, 3)' लैम्बडा क्या तर्क होगा? –

+0

आईडी पैरामीटर वास्तव में महत्वपूर्ण नहीं है। मेरे उपयोग-मामले में मैं इसे प्राप्त करने के लिए get_arg के अंदर उपयोग करता हूं ताकि यह पता लगाया जा सके कि टी का कौन सा उदाहरण लौटाएगा। लैम्ब्डा के लिए तर्क उम्मीद है कि टाइपलिस्ट में प्रत्येक प्रकार के लिए get_arg को कॉल करने के परिणाम होंगे, जैसा मैंने ऊपर लिखा था: 'func (* get_arg (आईडी), * get_arg (आईडी));' –

+0

संभावित डुप्लिकेट [मिलान करने वाले फ़ंक्शन पॉइंटर को कॉल करने के लिए एक टुपल को अनपॅक करना] [http://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function- सूचक) – TFM

उत्तर

1

सुनिश्चित नहीं है कि आप क्या चाहते हैं।

मैं विस्तार करने के लिए कैसे, call_func() अंदर, params_type के मापदंडों पैक पता नहीं लेकिन, यदि आप एक सहायक struct के उपयोग और सी ++ 14 के साथ एक संकलक बर्दाश्त ...

मैंने रिटर्न प्रकार के लिए समर्थन के साथ निम्नलिखित उदाहरण तैयार किया।

#include <tuple> 

template<typename F> 
struct function_traits; 

template<typename T, typename R, typename... Args> 
struct function_traits<R(T::*)(Args...) const> { 
    using return_type = R; 
    using param_types = std::tuple<Args...>; 
}; 

template<typename T> struct function_traits : public 
function_traits<decltype(&T::operator())> {}; 

template <typename T, typename ... Args> 
T get_arg (std::tuple<Args...> const & tpl) 
{ return std::get<typename std::decay<T>::type>(tpl); } 

template <typename ...> 
struct call_func_helper; 

template <typename Func, typename Ret, typename ... Args> 
struct call_func_helper<Func, Ret, std::tuple<Args...>> 
{ 
    template <typename T, typename R = Ret> 
     static typename std::enable_if<false == std::is_same<void, R>::value, R>::type 
       fn (Func const & func, T const & t) 
     { return func(get_arg<Args>(t)...); } 

    template <typename T, typename R = Ret> 
     static typename std::enable_if<true == std::is_same<void, R>::value, R>::type 
       fn (Func const & func, T const & t) 
     { func(get_arg<Args>(t)...); } 
}; 

template <typename Func, 
      typename T, 
      typename R = typename function_traits<Func>::return_type> 
R call_func (Func const & func, T const & id) 
{ 
    using param_types = typename function_traits<Func>::param_types; 

    return call_func_helper<Func, R, param_types>::fn(func, id); 
} 

int main() 
{ 
    call_func([](int const & a, char const & b) { }, std::make_tuple(3, '6')); 

    return 0; 
} 

उम्मीद है कि इससे मदद मिलती है।

+0

अच्छा!मुझे इसके चारों ओर अपने सिर को लपेटना है, लेकिन मुझे लगता है कि यह सब कुछ मुझे चाहिए। मैं (सुखद) हैरान हूं कि आप लैम्बडा के लिए विशेषज्ञता के रूप में '> 'का उपयोग करने में सक्षम हैं? मैंने सोचा होगा कि इसे 'function_traits' पर uglier 'R (T :: *) (Args ...) const' विशेषज्ञता की तरह दिखने की आवश्यकता होगी। –

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