M
mlimber
Hi, I'm interested in detecting traits for function pointer,
std::functions, functors (including lambdas), and std::bind
expressions. At present I only care about nullary (i.e., no
parameters) and unary (i.e., one parameter) functions, and I want to
use these traits to wrap them up in a std::function object of the
appropriate type. Here's what I came up with for function pointers and
std::functions:
namespace nsDetail
{
class Dummy { Dummy(); };
}
template<class Fn> struct FnTraits;
template<class R>
struct FnTraits<R(*)()>
{
typedef nsDetail:ummy ParamType;
typedef R ReturnType;
typedef R Signature();
static const bool IsNullary = true;
};
template<class R, class P>
struct FnTraits<R(*)(P)>
{
typedef P ParamType;
typedef R ReturnType;
typedef R Signature( P );
static const bool IsNullary = false;
};
template<class R>
struct FnTraits< std::function<R()> >
{
typedef nsDetail:ummy ParamType;
typedef R ReturnType;
typedef R Signature();
static const bool IsNullary = true;
};
template<class R, class P>
struct FnTraits< std::function<R(P)> >
{
typedef P ParamType;
typedef R ReturnType;
typedef R Signature( P );
static const bool IsNullary = false;
};
Here's an example of how I use it -- I have some given functions that
accept std::function objects with two signatures:
void DoSomething( std::function<void()> ) { /*...*/ }
void DoSomething( std::function<void(int)> ) { /*...*/ }
I want to automate the conversion to std::function that is sometimes
required in the client code to resolve ambiguity. To do this, I'm
trying something like:
template<class Fn>
void Wrap( Fn fn )
{
// Wrap it up as a std::function and pass it in
DoSomething( std::function<
typename FnTraits<Fn>::Signature >( fn ) );
}
struct Functor
{
void operator()(int) const;
};
void Bar( int );
void Foo()
{
DoSomething( std::function<void()>( []{} ) ); // Ok
DoSomething( &Bar ); // ambiguous
DoSomething( []{} ); // ambiguous
DoSomething( Functor() ); // ambiguous
DoSomething( std::bind( Bar, 42 ) ); // ambiguous
Wrap( std::function<void()>( []{} ) ); // Ok
Wrap( &Bar ); // Ok
Wrap( []{} ); // error
Wrap( Functor() ); // error
Wrap( std::bind( Bar, 42 ) ); // error
}
How can I get general functors and bind expressions in my FnTraits
class? It doesn't have to be bulletproof in detecting every case, as
the uses for it are well-defined within my program. There will only be
one operator() per functor.
TIA! --M
std::functions, functors (including lambdas), and std::bind
expressions. At present I only care about nullary (i.e., no
parameters) and unary (i.e., one parameter) functions, and I want to
use these traits to wrap them up in a std::function object of the
appropriate type. Here's what I came up with for function pointers and
std::functions:
namespace nsDetail
{
class Dummy { Dummy(); };
}
template<class Fn> struct FnTraits;
template<class R>
struct FnTraits<R(*)()>
{
typedef nsDetail:ummy ParamType;
typedef R ReturnType;
typedef R Signature();
static const bool IsNullary = true;
};
template<class R, class P>
struct FnTraits<R(*)(P)>
{
typedef P ParamType;
typedef R ReturnType;
typedef R Signature( P );
static const bool IsNullary = false;
};
template<class R>
struct FnTraits< std::function<R()> >
{
typedef nsDetail:ummy ParamType;
typedef R ReturnType;
typedef R Signature();
static const bool IsNullary = true;
};
template<class R, class P>
struct FnTraits< std::function<R(P)> >
{
typedef P ParamType;
typedef R ReturnType;
typedef R Signature( P );
static const bool IsNullary = false;
};
Here's an example of how I use it -- I have some given functions that
accept std::function objects with two signatures:
void DoSomething( std::function<void()> ) { /*...*/ }
void DoSomething( std::function<void(int)> ) { /*...*/ }
I want to automate the conversion to std::function that is sometimes
required in the client code to resolve ambiguity. To do this, I'm
trying something like:
template<class Fn>
void Wrap( Fn fn )
{
// Wrap it up as a std::function and pass it in
DoSomething( std::function<
typename FnTraits<Fn>::Signature >( fn ) );
}
struct Functor
{
void operator()(int) const;
};
void Bar( int );
void Foo()
{
DoSomething( std::function<void()>( []{} ) ); // Ok
DoSomething( &Bar ); // ambiguous
DoSomething( []{} ); // ambiguous
DoSomething( Functor() ); // ambiguous
DoSomething( std::bind( Bar, 42 ) ); // ambiguous
Wrap( std::function<void()>( []{} ) ); // Ok
Wrap( &Bar ); // Ok
Wrap( []{} ); // error
Wrap( Functor() ); // error
Wrap( std::bind( Bar, 42 ) ); // error
}
How can I get general functors and bind expressions in my FnTraits
class? It doesn't have to be bulletproof in detecting every case, as
the uses for it are well-defined within my program. There will only be
one operator() per functor.
TIA! --M