C++ SFINAE并检测是否存在C++;函数对象返回void
我已经阅读了有关这方面的各种权威,包括,但还没有设法解决这个看似简单的问题 < >我想做的是调用C++,(基本上,任何你可以调用的纯函数或类()),如果不是空虚的,或者“true”,则返回它的值。C++ SFINAE并检测是否存在C++;函数对象返回void,c++,sfinae,C++,Sfinae,我已经阅读了有关这方面的各种权威,包括,但还没有设法解决这个看似简单的问题 < >我想做的是调用C++,(基本上,任何你可以调用的纯函数或类()),如果不是空虚的,或者“true”,则返回它的值。 using std: struct Foo { void operator()() { cout << "Foo/"l; } }; struct Bar { bool operator()() { cout << "Bar/"; return 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
使用标准:
结构Foo{
void操作符()
template<class F>
class traits;
template<class F, class T>
class traits<T (F)()>;
template<class F>
class traits<void (F)()>;
模板
阶级特征;
模板
阶级特征;
模板
阶级特征;
我认为……使用C++0x,您可以通过使用decltype
轻松实现超负荷的无操作打印版本(void),不是更容易吗
嗯,函数模板和重载在运行时很容易处理这个问题
如果您想在编译时处理这个问题,那么它会变得有些棘手,因为它与#if宏或静态编译时断言一起使用
但既然你只想要前者,我可以建议你这样做作为起点:
(根据(GCC)3.4.4和4.0.1测试。--我知道,我需要升级!)
#包括
使用名称空间std;
结构Foo{
void运算符()({}
};
结构条{
bool运算符(){return false;}
};
富富,;
酒吧;
boolbaz(){return false;}
void bang(){}
结构IsVoid
{
typedef char YES[1];
typedef字符编号[2];
/*测试函数的无效返回值*/
模板
静态IsVoid::NO&testFunction(T(*f)();
静态IsVoid::YES&testFunction(void(*f)();
静态IsVoid::NO&testFunction(…);
/*测试“void operator()()”void返回值的对象*/
模板
结构hasOperatorMethodStruct{};
模板
静态是&测试方法(hasOperatorMethodStruct*);
模板
静态NO&testMethod(…);
/*调用函数对象方法以执行测试*/
模板
布尔运算符()(T&T)
{
返回((sizeof(IsVoid::testFunction(t))==sizeof(IsVoid::YES))
||(sizeof(IsVoid::testMethod(0))==sizeof(IsVoid::YES));
}
};
#定义BOUT(X)cout如果可以使用Boost
,下面的代码可能会起作用。
我假设所有的函数/函子都是空的,就像你的问题一样。
但是,为了使用此选项,必须在中定义result\u type
所有函子(函数类)
#包括
#包括
#包括
使用名称空间boost;//为了简洁起见,很抱歉
模板
//:类型的typename结果
typename禁用\u如果<
是否为void::type>
,typename result_of::type
>::类型
f(f常数和x)
{
返回x();
}
模板
typename启用\u如果<
是不是void::type>,bool
>::类型
f(f常数和x)
{
x();
返回true;
}
模板
tf(tx())
{
返回x();
}
bool f(void x())
{
x();
返回true;
}
静态void\u f(){}
静态int_f(){return 1;}
结构V{
typedef void result_type;
结果_类型运算符()()常量{}
};
结构A{
typedef int result_type;
结果_类型运算符()()常量{return 1;}
};
int main()
{
A A;
V V;
f(void_f);
f(int_f);
f(a);
f(v);
}
希望这有助于在编译时检测空返回值,标准技巧是重载运算符,
。逗号运算符的酷之处在于它可以接受一个空参数,在这种情况下,它默认为内置的运算符,
。在代码中:
template <typename> tag {};
template <typename T>
tag<T> operator,(T, tag<void>);
“印刷品”只是演示正在发生的事情…我正在包装方法和函数以传递给其他人的异步回调机制。我的大多数方法和函数返回void-有时我需要能够将布尔值返回给第三方异步回调。这非常巧妙!我没有掌握一个或两个技巧,而是三个技巧-一个是testFunction重载中的两个NO Case,一个是hasOperatorMethodStruct fiddle,一个是结合这两个条件的方式!非常有教育意义,我欠你一杯你选择的清爽饮料。好吧,抱歉,如果我在这里太过密集-但是现在我正在尝试适应它,我仍然不知道如何通用地调用func我现在明白为什么打印(void)不起作用了。调用部分被证明是具有挑战性的。也许我最新添加的内容会证明更有用,即使它很麻烦……你让我找到了一个更好的整体解决方案。请参阅我在原始帖子中的评论……你的表现令人印象深刻!
#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 );
}
#include <boost/utility/result_of.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
using namespace boost; // Sorry, for brevity
template< class F >
// typename result_of< F() >::type
typename disable_if<
is_void< typename result_of< F() >::type >
, typename result_of< F() >::type
>::type
f( F const& x )
{
return x();
}
template< class F >
typename enable_if<
is_void< typename result_of< F() >::type >, bool
>::type
f( F const& x )
{
x();
return true;
}
template< class T >
T f( T x() )
{
return x();
}
bool f( void x() )
{
x();
return true;
}
static void void_f() {}
static int int_f() { return 1; }
struct V {
typedef void result_type;
result_type operator()() const {}
};
struct A {
typedef int result_type;
result_type operator()() const { return 1; }
};
int main()
{
A a;
V v;
f( void_f );
f( int_f );
f( a );
f( v );
}
template <typename> tag {};
template <typename T>
tag<T> operator,(T, tag<void>);
char (&test(tag<void>))[1];
template <typename T> char (&test(tag<T>))[2];
template <typename F>
struct nullary_functor_traits
{
static const bool returns_void = sizeof(test((factory()(), tag<void>()))) == 1;
private:
static F factory();
};