प्रिंट (शून्य) का ओवरलोडेड नो-ऑप संस्करण लागू करना आसान नहीं होगा?
अहह ठीक है। फ़ंक्शन टेम्पलेट्स और ओवरलोडिंग आसानी से रनटाइम पर इसे संभालेंगे।
यदि आप #if मैक्रोज़ या स्थैतिक-संकलन-समय-आवेषण के साथ उपयोग के लिए संकलन समय पर इसे संभालना चाहते हैं तो यह कुछ हद तक चिपचिपा हो जाता है। । मुझे पता है, मैं अपग्रेड करने की आवश्यकता -
((जीसीसी) 3.4.4 & 4.0.1 के तहत परीक्षण किया गया:
लेकिन जब से तुम केवल पूर्व चाहते हैं, मैं एक प्रारंभिक बिंदु के रूप कुछ इस तरह का सुझाव दे सकते !)
#include <iostream>
using namespace std;
struct Foo {
void operator()() {}
};
struct Bar {
bool operator()() { return false; }
};
Foo foo;
Bar bar;
bool baz() { return false; }
void bang() {}
struct IsVoid
{
typedef char YES[1];
typedef char NO[2];
/* Testing functions for void return value. */
template <typename T>
static IsVoid::NO & testFunction(T (*f)());
static IsVoid::YES & testFunction(void (*f)());
static IsVoid::NO & testFunction(...);
/* Testing Objects for "void operator()()" void return value. */
template <typename C, void (C::*)()>
struct hasOperatorMethodStruct { };
template <typename C>
static YES & testMethod(hasOperatorMethodStruct<C, &C::operator()> *);
template <typename C>
static NO & testMethod(...);
/* Function object method to call to perform test. */
template <typename T>
bool operator() (T & t)
{
return ( (sizeof(IsVoid::testFunction(t)) == sizeof(IsVoid::YES))
|| (sizeof(IsVoid::testMethod<T>(0)) == sizeof(IsVoid::YES)));
}
};
#define BOUT(X) cout << # X " = " << boolToString(X) << endl;
const char * boolToString(int theBool)
{
switch (theBool)
{
case true: return "true";
case false: return "false";
default: return "unknownvalue";
}
}
int main()
{
IsVoid i;
BOUT(IsVoid()(foo));
BOUT(IsVoid()(bar));
BOUT(IsVoid()(baz));
BOUT(IsVoid()(bang));
cout << endl;
BOUT(i(foo));
BOUT(i(bar));
BOUT(i(baz));
BOUT(i(bang));
}
ठीक है, मैं इस समस्या के और अधिक देखने लगते हैं।
हम इस की तर्ज पर कुछ कर सकते हैं जबकि:
#include <iostream>
using namespace std;
struct FooA {
void operator()() {}
};
struct FooB {
bool operator()() { return false; }
};
struct FooC {
int operator()() { return 17; }
};
struct FooD {
double operator()() { return 3.14159; }
};
FooA fooA;
FooB fooB;
FooC fooC;
FooD fooD;
void barA() {}
bool barB() { return false; }
int barC() { return 17; }
double barD() { return 3.14159; }
namespace N
{
/* Functions */
template <typename R>
R run(R (*f)()) { return (*f)(); }
bool run(void (*f)()) { (*f)(); return true; }
/* Methods */
template <typename T, typename R>
R run(T & t, R (T::*f)()) { return (t .* f)(); }
template <typename T>
bool run(T & t, void (T::*f)()) { (t .* f)(); return true; }
};
#define SHOW(X) cout << # X " = " << (X) << endl;
#define BOUT(X) cout << # X " = " << boolToString(X) << endl;
const char * boolToString(int theBool)
{
switch (theBool)
{
case true: return "true";
case false: return "false";
default: return "unknownvalue";
}
}
int main()
{
SHOW(N::run(barA));
BOUT(N::run(barA));
SHOW(N::run(barB));
BOUT(N::run(barB));
SHOW(N::run(barC));
SHOW(N::run(barD));
cout << endl;
SHOW(N::run(fooA,&FooA::operator()));
BOUT(N::run(fooA,&FooA::operator()));
SHOW(N::run(fooB,&FooB::operator()));
BOUT(N::run(fooB,&FooB::operator()));
SHOW(N::run(fooC,&FooC::operator()));
SHOW(N::run(fooD,&FooD::operator()));
}
तुम अब भी है कि एक तर्क के रूप & क्लास :: ऑपरेटर() को खिलाने के लिए बुरा जरूरत होती है।
अंततः, हम तय कर सकते हैं, जबकि वस्तु की ऑपरेटर() विधि एक शून्य रिटर्न या नहीं, हम आम तौर पर अधिभार वापसी प्रकार के आधार पर नहीं कर सकते।
हम टेम्पलेट विशेषज्ञता के माध्यम से उस ओवरलोडिंग सीमा के आसपास हो सकते हैं। लेकिन फिर हम इस बदसूरतता में आते हैं जिसमें हमें अभी भी प्रकार निर्दिष्ट करने की आवश्यकता है ... विशेष रूप से वापसी का प्रकार! या तो मैन्युअल रूप से, या उपयुक्त तर्क में गुजरकर जिससे हम आवश्यक प्रकार निकाल सकते हैं।
बीटीडब्ल्यू: # परिभाषित मैक्रोज़ या तो मदद नहीं करेगा। उपकरण जैसे?: दोनों के लिए एक ही प्रकार की आवश्यकता है? और: भाग।
तो यह सबसे अच्छा मैं क्या कर सकते हैं ...
बेशक
...
आप वापसी प्रकार की जरूरत नहीं है ...
यदि आप परिणाम को किसी अन्य फ़ंक्शन पर पास कर रहे हैं ...
आप ऐसा कुछ कर सकते हैं:
#include <iostream>
using namespace std;
struct FooA {
void operator()() {}
};
struct FooB {
bool operator()() { return false; }
};
struct FooC {
int operator()() { return 17; }
};
struct FooD {
double operator()() { return 3.14159; }
};
FooA fooA;
FooB fooB;
FooC fooC;
FooD fooD;
void barA() {}
bool barB() { return false; }
int barC() { return 17; }
double barD() { return 3.14159; }
#define SHOW(X) cout << # X " = " << (X) << endl;
namespace N
{
template <typename T, typename R>
R run(T & t, R (T::*f)()) { return (t .* f)(); }
template <typename T>
bool run(T & t, void (T::*f)()) { (t .* f)(); return true; }
template <typename T>
void R(T & t)
{
SHOW(N::run(t, &T::operator()));
}
template <typename T>
void R(T (*f)())
{
SHOW((*f)());
}
void R(void (*f)())
{
(*f)();
SHOW(true);
}
};
int main()
{
N::R(barA);
N::R(barB);
N::R(barC);
N::R(barD);
N::R(fooA);
N::R(fooB);
N::R(fooC);
N::R(fooD);
}
इसका परीक्षण किया और यह जीसीसी 4.2.1 पर काम करता है। –
"प्रिंट" सिर्फ यह तय करने के लिए है कि क्या हो रहा है ... मैं जो कर रहा हूं वह किसी और के एसिंच कॉलबैक तंत्र को पास करने के लिए तरीकों और कार्यों को लपेट रहा है। मेरी अधिकांश विधियां और फ़ंक्शंस शून्य हो जाती हैं - कभी-कभी मुझे तीसरे पक्ष के एसिंक कॉलबैक में बुलियन लौटने में सक्षम होना चाहिए। –
यह बहुत चालाक है! एक या दो नहीं हैं लेकिन तीन चालें मुझे सही नहीं मिलीं - टेस्टफंक्शन के अधिभार में दो कोई भी मामला नहीं है, एक है ओपेरेटर मोडरस्ट्रक्चर फीडल, और इन दोनों स्थितियों को जोड़ने का तरीका है! बहुत शैक्षिक, मैं आपको अपनी पसंद का एक ताज़ा पेय देता हूं। –