2011-01-22 15 views
11

मैं, जो signature_of एक समारोह (सूचक), functor, या लैम्ब्डा के प्रकार को देखते हुए उसके हस्ताक्षर रिटर्न नाम के एक metafunction लिखने के लिए कोशिश कर रहा हूँ के हस्ताक्षर प्राप्त करने के लिए।कैसे एक सी ++ बाँध (...) अभिव्यक्ति

यहाँ मैं अब तक है:

#include <boost/mpl/pop_front.hpp> 
#include <boost/mpl/push_front.hpp> 
#include <boost/function_types/is_member_function_pointer.hpp> 
#include <boost/function_types/function_type.hpp> 
#include <boost/function_types/result_type.hpp> 
#include <boost/function_types/parameter_types.hpp> 

#include <type_traits> 

template <typename F> 
struct signature_of_member 
{ 
    typedef typename boost::function_types::result_type<F>::type result_type; 
    typedef typename boost::function_types::parameter_types<F>::type parameter_types; 
    typedef typename boost::mpl::pop_front<parameter_types>::type base; 
    typedef typename boost::mpl::push_front<base, result_type>::type L; 
    typedef typename boost::function_types::function_type<L>::type type; 
}; 

template <typename F, bool is_class> 
struct signature_of_impl 
{ 
    typedef typename boost::function_types::function_type<F>::type type; 
}; 

template <typename F> 
struct signature_of_impl<F, true> 
{ 
    typedef typename signature_of_member<decltype(&F::operator())>::type type; 
}; 

template <typename F> 
struct signature_of 
{ 
    typedef typename signature_of_impl<F, std::is_class<F>::value>::type type; 
}; 

यह बिल्कुल स्पष्ट है के साथ वास्तविक कार्य की सबसे बढ़ावा :: function_types पुस्तकालय द्वारा किया जा रहा। सामान्य विचार है:

  • उपयोग std :: is_class बिल्ट-इन कार्य ( lambdas सहित) और functors
  • में निर्मित समारोह प्रकार के लिए
  • , उपयोग को बढ़ावा देने :: function_types :: function_type के बीच भेदभाव करने , उसके हस्ताक्षर
  • functors के लिए
  • मिल उनके ऑपरेटर() के प्रकार के प्राप्त करने के लिए, उसके हस्ताक्षर मिलता है, और यह डॉक्टर "इस" पैरामीटर

यह बिल्ट-इन कार्य के लिए काम करता है दूर करने के लिए:

int f(int); 
typedef signature_of<decltype(f)>::type Sig; // Sig is int(int) 
lambdas के लिए

:

auto f = [](int) { return 0; } 
typedef signature_of<decltype(f)>::type Sig; // Sig is int(int) 

functors के लिए:

struct A 
{ 
    int operator()(int); 
}; 
typedef signature_of<A>::type Sig; // Sig is int(int) 

हालांकि, यह बाँध के लिए काम नहीं करता है() भाव (जो functors का एक विशेष मामला है)। अगर मैं इस प्रयास करें:

In file included from test.cpp:3:0: 
signature_of.hpp: In instantiation of 'signature_of_impl< 
     _Bind<int (*(int))(int)>, true 
    >': 
signature_of.hpp:45:74: instantiated from 'signature_of< 
     _Bind<int (*(int))(int)> 
    >' 
test.cpp:21:52: instantiated from here 
signature_of.hpp:39:74: error: type of '& _Bind< 
     int (*)(int)({int} ...) 
    >::operator()' is unknown 

समस्या यह है कि() functor बाँध द्वारा लौटाए के ऑपरेटर() एक टेम्पलेट है है, और इसलिए अपने प्रकार नहीं कर सकते हैं:

#include <functional> 
int g(int); 
typedef signature_of<decltype(std::bind(g, 0))>::type Sig; 

मैं एक संकलक त्रुटि मिलती है दृढ़ निश्चयी रहें।

यह एक बाँध() अभिव्यक्ति के हस्ताक्षर एक और तरीका प्राप्त करने के लिए संभव है?

+0

वीसी 10 इसे संकलित नहीं कर सकता है, त्रुटियां आमतौर पर बेवकूफ हैं ('त्रुटि C2039:' type ':' boost :: function_types :: result_type '') का सदस्य नहीं है, यह इस विशेषज्ञता को पसंद नहीं करता है:' typedef typename signature_of_member :: प्रकार का प्रकार; ' –

+0

@ एंडी टी: आप std :: फ़ंक्शन के टेम्पलेट पैरामीटर का उल्लेख किए बिना std :: फ़ंक्शन में कैसे परिवर्तित करते हैं, जो * हस्ताक्षर है * ? – HighCommander4

+0

हाँ, मेरी गलती, हटा रहा है ... –

उत्तर

11

आप तथ्य यह है कि एक बांधने की मशीन के ऑपरेटर() टेम्प्लेटेड है और अधिक से अधिक समस्याओं मिल गया है, यह भी मापदंडों के एक मनमाना संख्या अधिक है। याद रखें कि आप किसी भी अतिरिक्त तर्क के साथ बाध्य होने के परिणाम का आह्वान करने में सक्षम होना चाहिए। उदाहरण के लिए:

int f(int); 

auto bound = boost::bind(f, _2); 

bound अब 2 या अधिक के तर्कों के किसी भी संख्या के साथ कहा जा सकता है, केवल दूसरे वास्तव में कार्य करने के लिए पर भेजा जाता है।

तो बुनियादी तौर पर, के रूप में एक और उत्तर में कहा, इस वस्तु कोई हस्ताक्षर नहीं है। यह हस्ताक्षर केवल परिभाषित किया जाता है कि इसका उपयोग कैसे किया जाता है।

+0

अच्छा बिंदु, मुझे वास्तव में पता नहीं था कि आप इस तरह बांध() का उपयोग कर सकते हैं। – HighCommander4

4

यदि ऑपरेटर टेम्पलेट किया गया है, तो में कोई हस्ताक्षर नहीं है।

+0

या इसे थोड़ा अलग तरीके से देखकर, इसमें कोई अद्वितीय हस्ताक्षर नहीं है। 'ऑपरेटर()' को विभिन्न टेम्पलेट तर्कों के साथ तत्काल किया जा सकता है, और वे 'ऑपरेटर()' के उस तत्कालता के हस्ताक्षर में भाग लेते हैं। –

+2

हां, लेकिन यदि जी हस्ताक्षर int (int) है, तो अवधारणात्मक रूप से, बाध्य (जी, 0) हस्ताक्षर int (शून्य) होना चाहिए। तथ्य यह है कि std :: बाध्य कार्यान्वयन एक टेम्पलेट ऑपरेटर() का उपयोग करता है केवल एक कार्यान्वयन विस्तार है। – HighCommander4

+0

@ हाई कॉमांडर 4: अवधारणात्मक रूप से? किसे पड़ी है? तथ्य यह है कि ऐसा नहीं होने वाला है। यदि 'बाइंड' एक टेम्पलेट ऑपरेटर() के साथ एक मजेदार उत्पादक बनाता है, तो आप खराब हो जाते हैं, और आप जो भी चाहें अवधारणा कर सकते हैं, और यह उसे बदलने वाला नहीं है। – Puppy

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