2009-06-16 11:39:36 +02:00
/*
FUNCTION . hpp - metaprogramming utilities for transforming function types
2010-12-17 23:28:49 +01:00
2009-06-16 11:39:36 +02:00
Copyright ( C ) Lumiera . org
2009 , Hermann Vosseler < Ichthyostega @ web . de >
2010-12-17 23:28:49 +01:00
2009-06-16 11:39:36 +02:00
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
2010-12-17 23:28:49 +01:00
published by the Free Software Foundation ; either version 2 of
the License , or ( at your option ) any later version .
2009-06-16 11:39:36 +02:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2010-12-17 23:28:49 +01:00
2009-06-16 11:39:36 +02:00
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
2010-12-17 23:28:49 +01:00
2009-06-16 11:39:36 +02:00
*/
/** @file function.hpp
* * Metaprogramming tools for transforming functor types .
* * Sometimes it is necessary to build and remould a function signature , e . g . for
* * creating a functor or a closure based on an existing function of function pointer .
* * This is a core task of functional programming , but sadly C + + in its current shape
2017-03-19 02:07:18 +01:00
* * is still lacking in this area . ( C + + 11 significantly improved this situation ) .
2009-06-16 11:39:36 +02:00
* * As an \ em pragmatic fix , we define here a collection of templates , specialising
* * them in a very repetitive way for up to 9 function arguments . Doing so enables
* * us to capture a function , access the return type and argument types as a typelist ,
* * eventually to manipulate them and re - build a different signature , or to create
* * specifically tailored bindings .
* *
* * If the following code makes you feel like vomiting , please look away ,
2016-03-25 19:58:09 +01:00
* * and rest assured : you aren ' t alone .
* *
2017-03-19 02:07:18 +01:00
* * @ todo get rid of the repetitive specialisations
* * and use variadic templates to represent the arguments /////////////////////////////////TICKET #994
2016-03-25 19:58:09 +01:00
* *
2009-06-16 11:39:36 +02:00
* *
* * @ see control : : CommandDef usage example
2009-06-17 06:55:18 +02:00
* * @ see function - closure . hpp generic function application
2009-06-16 11:39:36 +02:00
* * @ see typelist . hpp
* * @ see tuple . hpp
* *
*/
2011-12-03 02:56:50 +01:00
# ifndef LIB_META_FUNCTION_H
# define LIB_META_FUNCTION_H
2009-06-16 11:39:36 +02:00
# include "lib/meta/typelist.hpp"
2017-11-24 02:48:16 +01:00
# include "lib/meta/util.hpp"
2009-06-16 11:39:36 +02:00
2014-04-03 22:42:48 +02:00
# include <functional>
2009-06-16 11:39:36 +02:00
2011-12-03 02:56:50 +01:00
namespace lib {
namespace meta {
2009-06-16 11:39:36 +02:00
2014-04-03 22:42:48 +02:00
using std : : function ;
2009-06-17 06:55:18 +02:00
2012-06-28 03:42:48 +02:00
/**
2017-03-19 02:07:18 +01:00
* Helper for uniform access to function signature types .
* Extract the type information contained in a function or functor type ,
2018-03-26 07:47:59 +02:00
* so it can be manipulated by metaprogramming . This template works on
2017-03-19 02:07:18 +01:00
* anything _function like_ , irrespective if the parameter is given
* as function reference , function pointer , member function pointer ,
2018-03-26 07:47:59 +02:00
* functor object , ` std : : function ` or lambda . The embedded typedefs
* allow to pick up
* - ` Ret ` : the return type
* - ` Args ` : the sequence of argument types as type sequence ` Types < ARGS . . . > `
* - ` Sig ` : the bare function signature type
* - ` Functor ` : corresponding Functor type which can be instantiated or copied .
2017-03-19 02:07:18 +01:00
*
2017-11-24 02:48:16 +01:00
* This template can also be used in metaprogramming with ` enable_if ` to enable
* some definition or specialisation only if a function - like type was detected ; thus
* the base case holds no nested type definitions and inherits from std : : false_type .
* The primary , catch - all case gets activated whenever on functor objects , i . e . anything
* with an ` operator ( ) ` .
2017-03-19 02:07:18 +01:00
* The following explicit specialisations handle the other cases , which are
* not objects , but primitive types ( function ( member ) pointers and references ) .
* @ remarks The key trick of this solution is to rely on ` decltype ` of ` operator ( ) `
2022-09-27 01:51:21 +02:00
* and was proposed 10 / 2011 by user « [ kennytm ] » in this [ stackoverflow ] .
2017-03-19 02:29:39 +01:00
* @ note for a member pointer to function , only the actual arguments in the
* function signature are reflected . But if you bind such a member
* pointer into a ` std : : function ` , an additional first parameter
* will show up to take the ` this ` pointer of the class instance .
2017-11-24 02:48:16 +01:00
* @ warning this detection scheme fails when the signature of a function call
* operator is ambiguous , which is especially the case
* - when there are several overloads of ` operator ( ) `
* - when the function call operator is templated
* - on * generic lambdas *
* All these cases will activate the base ( false ) case , as if the
* tested subject was not a function at all . Generally speaking ,
* it is _not possible_ to probe a generic lambda or templated function ,
* unless you bind it beforehand into a std : : function with correct signature .
2017-03-19 02:29:39 +01:00
* @ see FunctionSignature_test
2017-03-19 02:07:18 +01:00
*
* [ kennytm ] : http : //stackoverflow.com/users/224671/kennytm
2022-09-27 01:51:21 +02:00
* [ stackoverflow ] : http : //stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765 "figure out parameter and return type of a Lambda"
2012-06-28 03:42:48 +02:00
*/
2017-11-24 02:48:16 +01:00
template < typename FUN , typename SEL = void >
2012-06-28 03:42:48 +02:00
struct _Fun
2017-11-24 02:48:16 +01:00
: std : : false_type
2018-03-24 02:19:49 +01:00
{
using Functor = FUN ;
} ;
2017-11-24 02:48:16 +01:00
/** Specialisation for function objects and lambdas */
template < typename FUN >
struct _Fun < FUN , enable_if < has_FunctionOperator < FUN > > >
Functor-Tools: reshape generic function signature trait to integrate Lambdas (#994)
As a first step towards a gradual rework of our function metaprogramming helpers,
this change prepends a generic case for all kinds of functors to our existing
solution, which up to now was entirely based on explicit specialisations.
C++11 supplied the new language construct 'decltype(EXPR)', which allows us
to capture any class with an function operator, which also includes the Lambdas.
The solution was proposed 2011 on StackOverflow
http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765
We used it already with success within our TreeMutator.
But obviously the goal should be to unite all the function trait / metaprogramming helpers,
which unfortunately is a more expensive undertaking, since it also involves
to get rid of the explicit specialisations and retrofit our Types<XXX...> helper
to rely on variadic templates rather than on loki-style typelists.
This first step here is rather conservative, since we'll still rely on our
explicit specialisations in most cases. Only the Lambdas will go through the
new, generic case, and from there invoke the specialisation for member functions.
The latter need to be rectified as well, which is subject of the next changeset...
2017-03-18 22:06:44 +01:00
: _Fun < decltype ( & FUN : : operator ( ) ) >
2018-03-24 02:19:49 +01:00
{
using Functor = FUN ;
} ;
Functor-Tools: reshape generic function signature trait to integrate Lambdas (#994)
As a first step towards a gradual rework of our function metaprogramming helpers,
this change prepends a generic case for all kinds of functors to our existing
solution, which up to now was entirely based on explicit specialisations.
C++11 supplied the new language construct 'decltype(EXPR)', which allows us
to capture any class with an function operator, which also includes the Lambdas.
The solution was proposed 2011 on StackOverflow
http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765
We used it already with success within our TreeMutator.
But obviously the goal should be to unite all the function trait / metaprogramming helpers,
which unfortunately is a more expensive undertaking, since it also involves
to get rid of the explicit specialisations and retrofit our Types<XXX...> helper
to rely on variadic templates rather than on loki-style typelists.
This first step here is rather conservative, since we'll still rely on our
explicit specialisations in most cases. Only the Lambdas will go through the
new, generic case, and from there invoke the specialisation for member functions.
The latter need to be rectified as well, which is subject of the next changeset...
2017-03-18 22:06:44 +01:00
/** Specialisation for a bare function signature */
template < typename RET , typename . . . ARGS >
struct _Fun < RET ( ARGS . . . ) >
2017-11-24 02:48:16 +01:00
: std : : true_type
2012-06-28 03:42:48 +02:00
{
2017-03-19 02:07:18 +01:00
using Ret = RET ;
using Args = Types < ARGS . . . > ;
Functor-Tools: reshape generic function signature trait to integrate Lambdas (#994)
As a first step towards a gradual rework of our function metaprogramming helpers,
this change prepends a generic case for all kinds of functors to our existing
solution, which up to now was entirely based on explicit specialisations.
C++11 supplied the new language construct 'decltype(EXPR)', which allows us
to capture any class with an function operator, which also includes the Lambdas.
The solution was proposed 2011 on StackOverflow
http://stackoverflow.com/questions/7943525/is-it-possible-to-figure-out-the-parameter-type-and-return-type-of-a-lambda/7943765#7943765
We used it already with success within our TreeMutator.
But obviously the goal should be to unite all the function trait / metaprogramming helpers,
which unfortunately is a more expensive undertaking, since it also involves
to get rid of the explicit specialisations and retrofit our Types<XXX...> helper
to rely on variadic templates rather than on loki-style typelists.
This first step here is rather conservative, since we'll still rely on our
explicit specialisations in most cases. Only the Lambdas will go through the
new, generic case, and from there invoke the specialisation for member functions.
The latter need to be rectified as well, which is subject of the next changeset...
2017-03-18 22:06:44 +01:00
using Sig = RET ( ARGS . . . ) ;
2018-03-24 02:19:49 +01:00
using Functor = std : : function < Sig > ;
2023-10-10 19:47:39 +02:00
enum { ARITY = sizeof . . . ( ARGS ) } ;
2012-06-28 03:42:48 +02:00
} ;
2020-02-21 20:15:21 +01:00
/** Specialisation to strip `noexcept` from the signature */
template < typename RET , typename . . . ARGS >
struct _Fun < RET ( ARGS . . . ) noexcept >
: _Fun < RET ( ARGS . . . ) >
{ } ;
2012-06-28 03:42:48 +02:00
/** Specialisation for using a function pointer */
template < typename SIG >
struct _Fun < SIG * >
2017-03-19 02:07:18 +01:00
: _Fun < SIG >
{ } ;
2012-09-01 17:33:42 +02:00
/** Specialisation when using a function reference */
template < typename SIG >
struct _Fun < SIG & >
2017-03-19 02:07:18 +01:00
: _Fun < SIG >
{ } ;
2012-06-28 03:42:48 +02:00
2017-03-19 02:07:18 +01:00
/** Specialisation for passing a rvalue reference */
template < typename SIG >
struct _Fun < SIG & & >
: _Fun < SIG >
{ } ;
2012-06-28 03:42:48 +02:00
2017-03-19 02:07:18 +01:00
/** Specialisation to deal with member pointer to function */
template < class C , typename RET , typename . . . ARGS >
struct _Fun < RET ( C : : * ) ( ARGS . . . ) >
: _Fun < RET ( ARGS . . . ) >
{ } ;
2012-06-28 03:42:48 +02:00
2020-02-21 20:15:21 +01:00
/** Specialisation to deal with member pointer to noexcept function */
template < class C , typename RET , typename . . . ARGS >
struct _Fun < RET ( C : : * ) ( ARGS . . . ) noexcept >
: _Fun < RET ( ARGS . . . ) >
{ } ;
2017-03-19 02:07:18 +01:00
/** Specialisation to handle member pointer to const function;
* indirectly this specialisation also handles lambdas ,
* as redirected by the main template ( via ` decltype ` ) */
template < class C , typename RET , typename . . . ARGS >
struct _Fun < RET ( C : : * ) ( ARGS . . . ) const >
: _Fun < RET ( ARGS . . . ) >
{ } ;
2012-06-28 03:42:48 +02:00
2023-05-04 12:35:23 +02:00
/**
* Meta - function to check that some _function like_ entity
* offers the expected signature
* @ tparam SIG signature type ( e . g . ` float ( int , bool ) ` )
* @ tparam FUN anything _function like_ ( class with function call operator
* or std : : function instance , or λ instance or language function
* reference or function pointer
*/
template < typename FUN , typename SIG >
struct has_Sig
: std : : is_same < SIG , typename _Fun < FUN > : : Sig >
{ } ;
/**
* Macro for a compile - time check to verify the given
* generic functors or lambdas expose some expected signature .
* @ remark typically used when configuring a template with custom adapters .
*/
# define ASSERT_VALID_SIGNATURE(_FUN_, _SIG_) \
static_assert ( lib : : meta : : has_Sig < _FUN_ , _SIG_ > : : value , \
" Function " STRINGIFY ( _FUN_ ) " unsuitable, expected signature: " STRINGIFY ( _SIG_ ) ) ;
2012-06-28 03:42:48 +02:00
2009-06-17 06:55:18 +02:00
/**
* Build function types from given Argument types .
* As embedded typedefs , you ' ll find a tr1 functor # Func
* and the bare function signature # Sig
* @ param RET the function return type
* @ param ARGS a type sequence describing the arguments
*/
template < typename RET , typename ARGS >
2009-06-16 11:39:36 +02:00
struct FunctionTypedef ;
2009-06-17 06:55:18 +02:00
2009-06-16 11:39:36 +02:00
template < typename RET >
struct FunctionTypedef < RET , Types < > >
{
typedef function < RET ( void ) > Func ;
typedef RET Sig ( ) ;
} ;
2009-06-17 06:55:18 +02:00
2009-06-16 11:39:36 +02:00
template < typename RET
, typename A1
>
2016-12-23 04:23:03 +01:00
struct FunctionTypedef < RET , Types < A1 > >
2009-06-16 11:39:36 +02:00
{
typedef function < RET ( A1 ) > Func ;
typedef RET Sig ( A1 ) ;
} ;
2009-06-17 06:55:18 +02:00
2009-06-16 11:39:36 +02:00
template < typename RET
, typename A1
, typename A2
>
2016-12-23 04:23:03 +01:00
struct FunctionTypedef < RET , Types < A1 , A2 > >
2009-06-16 11:39:36 +02:00
{
typedef function < RET ( A1 , A2 ) > Func ;
typedef RET Sig ( A1 , A2 ) ;
} ;
2009-06-17 06:55:18 +02:00
2009-06-16 11:39:36 +02:00
template < typename RET
, typename A1
, typename A2
, typename A3
>
2016-12-23 04:23:03 +01:00
struct FunctionTypedef < RET , Types < A1 , A2 , A3 > >
2009-06-16 11:39:36 +02:00
{
typedef function < RET ( A1 , A2 , A3 ) > Func ;
typedef RET Sig ( A1 , A2 , A3 ) ;
} ;
2009-06-17 06:55:18 +02:00
2009-06-16 11:39:36 +02:00
template < typename RET
, typename A1
, typename A2
, typename A3
, typename A4
>
2016-12-23 04:23:03 +01:00
struct FunctionTypedef < RET , Types < A1 , A2 , A3 , A4 > >
2009-06-16 11:39:36 +02:00
{
typedef function < RET ( A1 , A2 , A3 , A4 ) > Func ;
typedef RET Sig ( A1 , A2 , A3 , A4 ) ;
} ;
2009-06-17 06:55:18 +02:00
2009-06-16 11:39:36 +02:00
template < typename RET
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
>
2016-12-23 04:23:03 +01:00
struct FunctionTypedef < RET , Types < A1 , A2 , A3 , A4 , A5 > >
2009-06-16 11:39:36 +02:00
{
typedef function < RET ( A1 , A2 , A3 , A4 , A5 ) > Func ;
typedef RET Sig ( A1 , A2 , A3 , A4 , A5 ) ;
} ;
2009-06-17 06:55:18 +02:00
template < typename RET
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
, typename A6
>
2016-12-23 04:23:03 +01:00
struct FunctionTypedef < RET , Types < A1 , A2 , A3 , A4 , A5 , A6 > >
2009-06-17 06:55:18 +02:00
{
typedef function < RET ( A1 , A2 , A3 , A4 , A5 , A6 ) > Func ;
typedef RET Sig ( A1 , A2 , A3 , A4 , A5 , A6 ) ;
} ;
2009-06-16 11:39:36 +02:00
2009-06-17 06:55:18 +02:00
template < typename RET
, typename A1
2009-06-16 11:39:36 +02:00
, typename A2
, typename A3
, typename A4
, typename A5
2009-06-17 06:55:18 +02:00
, typename A6
, typename A7
2009-06-16 11:39:36 +02:00
>
2016-12-23 04:23:03 +01:00
struct FunctionTypedef < RET , Types < A1 , A2 , A3 , A4 , A5 , A6 , A7 > >
2009-06-16 11:39:36 +02:00
{
2009-06-17 06:55:18 +02:00
typedef function < RET ( A1 , A2 , A3 , A4 , A5 , A6 , A7 ) > Func ;
typedef RET Sig ( A1 , A2 , A3 , A4 , A5 , A6 , A7 ) ;
2009-06-16 11:39:36 +02:00
} ;
2009-06-17 06:55:18 +02:00
template < typename RET
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
, typename A6
, typename A7
, typename A8
>
2016-12-23 04:23:03 +01:00
struct FunctionTypedef < RET , Types < A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 > >
2009-06-17 06:55:18 +02:00
{
typedef function < RET ( A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 ) > Func ;
typedef RET Sig ( A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 ) ;
} ;
2009-06-16 11:39:36 +02:00
2009-06-17 06:55:18 +02:00
template < typename RET
, typename A1
, typename A2
, typename A3
, typename A4
, typename A5
, typename A6
, typename A7
, typename A8
, typename A9
>
2016-12-23 04:23:03 +01:00
struct FunctionTypedef < RET , Types < A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 , A9 > >
2009-06-17 06:55:18 +02:00
{
typedef function < RET ( A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 , A9 ) > Func ;
typedef RET Sig ( A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 , A9 ) ;
} ;
2009-06-16 11:39:36 +02:00
2011-12-03 02:56:50 +01:00
} } // namespace lib::meta
2009-06-16 11:39:36 +02:00
# endif