पर विशेषज्ञता टाइप करें मैं एक कक्षा लिख रहा हूं जो std::function
(या कम से कम कक्षाएं कई तरीकों से समान हैं) के साथ कई अलग-अलग विशेषताएं साझा करती हैं। जैसा कि आप सभी जानते हैं std::function
टेम्पलेट पैरामीटर (यानी std::function<void (std::string&)>
) निर्दिष्ट करके तत्काल है, यह मेरी कक्षा के लिए समान है। हालांकि, मेरे पास अपवाद है, यदि मैं वापसी मान शून्य है (std::function<"return value" ("parameters">
), तो मैं अपनी कक्षा में एकल फ़ंक्शन का विशेषज्ञ बनाना चाहता हूं। मुझे संकलन समय पर ऐसा करने की ज़रूरत है, और मैं इसे काम नहीं कर सकता क्योंकि इसे करना चाहिए। यहाँ विवरण के लिए कुछ परीक्षण कोड है:संकलन-समय
#include <iostream>
#include <type_traits>
template <typename T> class Test { };
template <typename Ret, typename... Args>
class Test<Ret (Args...)>
{
public:
Ret operator()(Args...)
{
if(std::is_void<Ret>::value)
{
// Do something...
}
else /* Not a void function */
{
Ret returnVal;
return returnVal;
}
}
};
int main(int argc, char * argv[])
{
Test<void (char)> test;
test('k');
}
आप स्पष्ट रूप से देख सकते हैं, अगर संकलक ऊपर की परीक्षा में 'शेष' शाखा को दूर नहीं करता, मेरे कोड एक शून्य मूल्य बनाने की कोशिश करेंगे (यानी void returnVal;
) । समस्या यह है कि संकलक तो मैं एक संकलक त्रुटि के साथ अंत शाखा को दूर नहीं करता है:
./test.cpp: In instantiation of ‘Ret Test::operator()(Args ...) [with Ret = void; Args = {char}]’: ./test.cpp:27:10: required from here ./test.cpp:18:8: error: variable or field ‘returnVal’ declared void ./test.cpp:19:11: error: return-statement with a value, in function returning 'void' [-fpermissive]
एक सामान्य रूप से उपयोग std::enable_if
std::is_void
के साथ संयुक्त होता है, समस्या यह है कि मैं पर विशेषज्ञ नहीं करना चाहती है फ़ंक्शन टेम्पलेट, लेकिन कक्षा टेम्पलेट पर।
template <typename Ret, typename... Args>
class Test<Ret (Args...)>
{
public:
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type
Ret operator()(Args...)
{
Ret returnVal;
return returnVal;
}
typename std::enable_if<std::is_void<Ret>::value, Ret>::type
Ret operator()(Args...)
{
// It's a void function
// ...
}
};
अगर मैं बजाय ऊपर कोड का उपयोग मैं भी अधिक त्रुटियों के साथ और एक समाधान
./test.cpp:11:2: error: expected ‘;’ at end of member declaration
./test.cpp:11:2: error: declaration of ‘typename std::enable_if<(! std::is_void<_Tp>::value), Ret>::type Test<Ret(Args ...)>::Ret’
./test.cpp:6:11: error: shadows template parm ‘class Ret’
./test.cpp:11:24: error: ISO C++ forbids declaration of ‘operator()’ with no type [-fpermissive]
./test.cpp:18:2: error: expected ‘;’ at end of member declaration
./test.cpp:18:2: error: declaration of ‘typename std::enable_if<std::is_void<_Tp>::value, Ret>::type Test<Ret(Args ...)>::Ret’
./test.cpp:6:11: error: shadows template parm ‘class Ret’
./test.cpp:18:24: error: ISO C++ forbids declaration of ‘operator()’ with no type [-fpermissive]
./test.cpp:18:6: error: ‘int Test<Ret(Args ...)>::operator()(Args ...)’ cannot be overloaded
./test.cpp:11:6: error: with ‘int Test<Ret(Args ...)>::operator()(Args ...)’
./test.cpp: In member function ‘int Test<Ret(Args ...)>::operator()(Args ...)’:
./test.cpp:22:2: warning: no return statement in function returning non-void [-Wreturn-type]
./test.cpp: In instantiation of ‘int Test<Ret(Args ...)>::operator()(Args ...) [with Ret = void; Args = {char}]’:
./test.cpp:28:10: required from here
./test.cpp:13:7: error: variable or field ‘returnVal’ declared void
./test.cpp: In member function ‘int Test<Ret(Args ...)>::operator()(Args ...) [with Ret = void; Args = {char}]’:
./test.cpp:15:2: warning: control reaches end of non-void function [-Wreturn-type]
अगर मैं सिर्फ सादा गूंगा कर रहा हूँ मैं माफी चाहता हूँ बिना खत्म, और जवाब स्पष्ट है। मैं टेम्पलेट्स के लिए बिल्कुल नया हूं और मुझे किसी भी अन्य थ्रेड/प्रश्नों में एक उपयुक्त उत्तर नहीं मिला।
"स्थिर अगर" शामिल करने का एक प्रस्ताव है जो आपके पहले उदाहरण में वही करेगा जो आप चाहते हैं। – mfontanini
@mfontanini: क्या वास्तव में आगे बढ़ने वाले दो प्रस्तावों में से कोई एक अलग मुद्दा है। उनके पास कमियां होती हैं और कुछ चीजें उन चीज़ों से अधिक जटिल हो जाती हैं, जिन्हें आप टेम्पलेट्स के साथ SFINAE का उपयोग करना शुरू करते हैं, जिसमें स्थिर हैं- –
"समस्या यह है कि संकलक शाखा को नहीं हटाता है इसलिए मैं एक कंपाइलर त्रुटि के साथ समाप्त होता हूं" = > दुर्भाग्यवश, कंपाइलर * की आवश्यकता नहीं है *, जो (मैं स्वीकार करता हूं) थोड़ा अचूक है। –