我已经阅读了有关这方面的各种权威,包括
Dewhurst但尚未设法通过这个看似简单的问题得到任何结果.
我想要做的是调用C function object,(基本上,你可以调用任何东西,纯函数或带()的类,并返回它的值,如果它不是空的,否则返回“true”.
using std: struct Foo { void operator()() { cout << "Foo/"l; } }; struct Bar { bool operator()() { cout << "Bar/"; return true; } }; Foo foo; Bar bar; bool baz() { cout << "baz/"; return true; } void bang() { cout << "bang/"; } const char* print(bool b) { cout << b ? "true/" : "false/"; } template <typename Functor> bool magicCallFunction(Functor f) { return true; // Lots of template magic occurs here // that results in the functor being called. } int main(int argc,char** argv) { print(magicCallFunction(foo)); print(magicCallFunction(bar)); print(magicCallFunction(baz)); print(magicCallFunction(bang)); printf("\n"); } // Results: Foo/true/Bar/true/baz/true/bang/true
UPDATE
感谢您的想法和想法!
基于此,我实际上决定提出我所有的模板 – 所以我有:
bool eval(bool (*f)()) { return (*f)(); } bool eval(void (*f)()) { (*f)(); return true; } template <typename Type> bool eval(Type* obj,bool (Type::*method)()) { return (obj->*method)(); } template <typename Type> bool eval(Type* obj,void (Type::*method)()) { (obj->*method)(); return true; }
解决方法
实现重载的无操作版print(void)会不会更容易?
啊好吧函数模板和重载将在运行时轻松处理.
如果你想在编译时处理它,与#if宏或static-compile-time-asserts一起使用,它会变得有点棘手.
但既然你只想要前者,我可以建议这样一个起点:
(根据(GCC)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())); }
你仍然需要将& CLASS :: operator()作为参数提供.
最终,虽然我们可以确定对象的operator()方法是否返回void,但我们通常不能基于返回类型重载.
我们可以通过模板专业化来解决这个超载限制.但后来我们陷入了这种丑陋,我们仍然需要指定类型……尤其是返回类型!手动,或通过传入一个合适的参数,我们可以从中提取必要的类型.
BTW:#define宏也无济于事.像?的工具:两者都需要相同的类型?和:部分.
所以这是我能做的最好的……
当然…
如果您不需要退货类型……
如果你只是将结果传递给另一个函数……
你可以这样做:
#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,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 ); }