फिलहाल मैं विभिन्न कॉलिंग सम्मेलनों (__stdcall, __cdecl, __fastcall इत्यादि) के लिए फ़ैक्टर (कॉल करने योग्य प्रकार) बना रहा हूं। के रूप में सही पैरामीटर निर्दिष्ट कर रहे हैं मैं __stdcall बुला परंपरा है कि जब तक किसी भी __stdcall फ़ंक्शन को कॉल करने में सक्षम है के लिए एक आवरण का निर्माण किया हैविभिन्न कॉलिंग सम्मेलनों के साथ कॉल करने योग्य ऑब्जेक्ट्स
void __stdcall foo(int arg)
{
std::printf("arg: %i\n", arg);
}
int main(int, char**)
{
Function<void, int> v{foo};
v(1337);
return EXIT_SUCCESS;
}
फिलहाल: रैपर के साथ मैं इस तरह कुछ करने के लिए सक्षम हो जाएगा और सही तर्क में पारित कर रहे हैं वर्ग इस तरह दिखता है:।
template <typename ReturnT, typename... Args>
class Function
{
// NOTE: This version of my callable types
// only supports the __stdcall calling
// convention. I need support for __cdecl,
// __fastcall and also __thiscall.
using return_t = ReturnT;
using callable_t = return_t(__stdcall*)(Args...);
private:
callable_t mCallable;
public:
template <typename FuncT>
Function(FuncT const &func) :
mCallable(func)
{
;
}
void operator()(Args&&... args)
{
mCallable(std::forward<Args>(args)...);
}
};
कि हाथ में मैं अन्य रैपर बनाने का निर्णय लिया साथ
लेकिन मैं लगा कि कोड के एक ही हिस्से को लिखकर और के अंदर बुला सम्मेलन को बदलने कॉल करने योग्य_टी के लिए उपयोग की घोषणा आवश्यकतानुसार अधिक काम है। तो मैं कॉल करने योग्य प्रकारों के बारे में 4 प्रकार (प्रत्येक कॉलिंग सम्मेलन के लिए) बनाने का एक तरीका खोजना चाहता था लेकिन इसे करने का कोई तरीका नहीं मिला।
अब तक मैं इस तरह एक गैर प्रकार टेम्पलेट पैरामीटर के रूप में एक enum का उपयोग करने की कोशिश की है:
template <CallingConvention Call, typename ReturnT, typename... ArgsT>
class Function
{
// ...
};
लेकिन मैं कॉल वस्तु के प्रकार पुनरावृति और आवश्यक प्रकार की स्थापना के लिए पता नहीं कैसे (मैं std :: is_same/std :: enable_if का उपयोग करने का प्रयास किया लेकिन यह एक मृत अंत था)। मैं भी इस तरह के कोड के साथ टेम्पलेट विशेषज्ञता की कोशिश की:
struct StdcallT { ; };
struct CdeclT { ; };
struct FastcallT { ; };
template <typename CallT>
struct BaseT { };
template <> struct BaseT<StdcallT> { using CallableT = void(__stdcall*)(); };
template <> struct BaseT<CdeclT> { using CallableT = void(__cdecl*)(); };
template <> struct BaseT<FastcallT> { using CallableT = void(__fastcall*)(); };
template <typename CallT>
class Function
{
using CallableT = typename BaseT<CallT>::CallableT;
};
लेकिन मैं तर्क के बाकी (वापसी प्रकार + पैरामीटर) के बारे में सोच नहीं किया गया था तो यह भी काम नहीं कर सकता।
तो क्या कोई विचार है कि मैं क्या कर सकता हूं? एक विधि मैं सोच रहा हूँ की गैर प्रकार पैरामीटर पर एक स्विच कर रहे हैं और इस तरह से सही बुला रहा है:
template <CallingConvention Call, typename ReturnT, typename... ArgsT>
class Function
{
void operator()(ArgsT&&... args)
{
switch(Call)
{
case CallingConvention::Cdecl:
// Call a __cdecl version
break;
case CallingConvention::Stdcall:
// Call an __stdcall version
break;
// And so on...
}
}
};
और इस के बावजूद एक काम कर समाधान अगर वहाँ था कुछ अच्छे विकल्प मैं सोच रहा था की तरह लग रही है कि मैं सोच नहीं रहा हूँ।
कोई विचार?
पहिया को फिर से क्यों शुरू करें? 'std :: function' पहले से ही किसी भी फ़ंक्शन पॉइंटर या फ़ैक्टर को स्टोर करने में सक्षम होना चाहिए, भले ही कॉलिंग कन्वेंशन के बावजूद, जब तक यह आपके द्वारा निर्दिष्ट तर्कों के साथ कॉल करने योग्य हो। क्या यह आपके लिए काम नहीं करता है, या क्या इसमें कुछ ठोस कमीएं हैं जो आपको अपने कस्टम कार्यान्वयन पर शुरू कर रही हैं? – hvd
@hvd मान लीजिए कि आपके पास std :: unordered_map मैपिंग स्ट्रिंग्स जैसे "glCreateProgram" और "glCreateShader" opengl32.dll से उनके प्रतीक पते पर लोड किए गए हैं। आप एक टेम्पलेटेड फ़ंक्शन function_cast <कॉलिंग कन्वेंशन, आउटपुट टाइप, इनपुट टाइप> बनाना चाहते हैं कि आप कोई तर्क/रिटर्न के लिए शून्य का उपयोग नहीं करेंगे, और std :: tuple args/no args के लिए, क्योंकि वे द्विआधारी संगत हैं। जैसा कि यह खड़ा है, std: फ़ंक्शन stdcall के लिए काम नहीं करता है, इसलिए एक रनटाइम अगर कुछ डमी कॉलिंग सम्मेलन पर चेक की आवश्यकता होती है जिसके आधार पर आप कॉलिंग कन्वेंशन कास्टिंग स्विच करते हैं। –
Dmitry
@Dmitry "std: function stdcall के लिए काम नहीं करता है" - जीसीसी के पुराने संस्करण (जीसीसी 5 तक) ने नामांकन में कॉलिंग सम्मेलन को अनदेखा कर दिया, जिससे लिंकर त्रुटियां आईं, लेकिन यह मध्य 2015 के मध्य में तय की गई थी, और वहां नहीं होना चाहिए तब से कम से कम उस कंपाइलर में गैर-डिफ़ॉल्ट कॉलिंग सम्मेलनों के लिए 'std :: function' के साथ समस्याएं हो। अन्य कंपाइलर्स * एक ही तरीके से काम करना चाहिए। यदि कोई नहीं करता है, तो क्या आप विवरण दे सकते हैं कि यह कौन सा है? – hvd