2009-06-16 11:39:36 +02:00
/*
FUNCTION . hpp - metaprogramming utilities for transforming function types
2010-12-17 23:28:49 +01:00
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
Copyright ( C )
2009 , Hermann Vosseler < Ichthyostega @ web . de >
2010-12-17 23:28:49 +01:00
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
* * Lumiera * * is free software ; you can redistribute it and / or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation ; either version 2 of the License , or ( at your
option ) any later version . See the file COPYING for further details .
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 >
{ } ;
2023-11-26 03:04:59 +01:00
/** Specialisation to strip spurious const for type analysis */
template < typename SIG >
struct _Fun < SIG const & >
: _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-10-21 23:42:31 +02:00
/** allow also to probe _plain member fields,_ which may hold a functor */
template < class C , typename FUN >
struct _Fun < FUN ( C : : * ) >
: _Fun < FUN >
{ } ;
2012-06-28 03:42:48 +02:00
2023-11-22 22:11:59 +01:00
/** abbreviation for referring to a function's return type */
template < typename FUN >
using _FunRet = typename _Fun < FUN > : : Ret ;
namespace {
template < typename FUN >
struct _DetectSingleArgFunction
{
static_assert ( _Fun < FUN > ( ) , " something funktion-like required " ) ;
static_assert ( _Fun < FUN > : : ARITY = = 1 , " function with exactly one argument required " ) ;
using Sig = typename _Fun < FUN > : : Sig ;
using Arg = typename _Fun < Sig > : : Args : : List : : Head ;
} ;
}
/** abbreviation for referring to a function's single Argument type */
template < typename FUN >
using _FunArg = typename _DetectSingleArgFunction < FUN > : : Arg ;
2023-12-09 02:36:14 +01:00
template < typename FUN , uint a >
using has_Arity = std : : bool_constant < _Fun < FUN > : : ARITY = = a > ;
template < typename FUN >
using is_NullaryFun = has_Arity < FUN , 0 > ;
template < typename FUN >
using is_UnaryFun = has_Arity < FUN , 1 > ;
template < typename FUN >
using is_BinaryFun = has_Arity < FUN , 2 > ;
2023-11-22 22:11:59 +01: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
*/
2023-10-21 23:42:31 +02:00
template < typename FUN , typename SIG , bool = _Fun < FUN > ( ) >
2023-05-04 12:35:23 +02:00
struct has_Sig
: std : : is_same < SIG , typename _Fun < FUN > : : Sig >
{ } ;
2023-10-21 23:42:31 +02:00
/** catch-all to prevent compilation failure for anything not function-like. */
template < typename FUN , typename X >
struct has_Sig < FUN , X , false >
: std : : false_type
{ } ;
2023-05-04 12:35:23 +02:00
/**
* 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_ ) ) ;
2023-10-21 23:42:31 +02:00
/**
* Helper to pick up a member field for verification
* @ tparam SIG signature of the _function like_ entity expected
* @ tparam FUN address - or member - pointer , e . g . ` & Class : : member `
* @ return suitably parametrised \ ref has_Sig instance ( which is bool convertible )
* @ remark intended for use with generic types , when expecting a _somehow invokable_
* member , irrespective if a static function , member function or functor object
*/
template < typename SIG , typename FUN >
constexpr inline auto
isFunMember ( FUN )
{
return has_Sig < FUN , SIG > { } ;
}
/**
* Macro for a compile - time check to verify some member is present
* and comprises something invokable with a specific signature .
* @ remark typically used with _generic types_ or bindings
*/
# define ASSERT_MEMBER_FUNCTOR(_EXPR_, _SIG_) \
static_assert ( lib : : meta : : isFunMember < _SIG_ > ( _EXPR_ ) , \
" Member " STRINGIFY ( _EXPR_ ) " unsuitable, expect function signature: " STRINGIFY ( _SIG_ ) ) ;
2023-05-04 12:35:23 +02:00
2012-06-28 03:42:48 +02:00
2023-10-11 21:06:56 +02:00
/** Placeholder marker for a special argument position to be supplied later */
template < class TAR >
struct InstancePlaceholder { } ;
namespace { // Helper to inject instance-pointer instead of placeholder...
/**
* @ internal helper to detect an InstancePlaceholder
* @ return an instance - pointer , statically casted to the marked target type .
*/
template < class W , class TAR >
constexpr inline TAR *
maybeInject ( W & instance , InstancePlaceholder < TAR > )
{
return static_cast < TAR * > ( & instance ) ;
}
/** (default case: fall-through) */
template < class W , typename X >
constexpr inline X
maybeInject ( W & , X & & x )
{
return std : : move ( x ) ;
}
} //(End)Helper for lateBindInstance.
/**
* Fix - up the arguments for a member - function invocation ,
* allowing to inject the actual ` this ` instance into an existing argument sequence .
* @ remark invocation of a member function requires to supply the _object instance_ as
* first element in the argument list ; sometimes this poses a design challenge ,
* since the actual instance may not be known at the point where the other arguments
* are prepared . As a remedy , the position of the instance pointer can be marked with
* the \ ref InstancePlaceholder , allowing to splice in the actual pointer when known .
*/
template < class W , class TUP >
constexpr inline auto
lateBindInstance ( W & instance , TUP & & invocation )
{
auto splice = [ & instance ] ( auto & & . . . xs )
{
return std : : tuple { maybeInject ( instance , std : : move ( xs ) ) . . . } ;
} ;
return std : : apply ( splice , std : : forward < TUP > ( invocation ) ) ;
}
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
2023-10-11 21:06:56 +02:00
*/ //////////////////////////////////////////////////////////////////////TICKET #987 : make lib::meta::Types<TYPES...> variadic, then replace this by a single variadic template
2009-06-17 06:55:18 +02:00
template < typename RET , typename ARGS >
2023-11-22 22:11:59 +01:00
struct BuildFunType ;
2009-06-16 11:39:36 +02:00
2009-06-17 06:55:18 +02:00
2009-06-16 11:39:36 +02:00
template < typename RET >
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < > >
2009-06-16 11:39:36 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( void ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
2009-06-16 11:39:36 +02:00
} ;
2009-06-17 06:55:18 +02:00
2009-06-16 11:39:36 +02:00
template < typename RET
, typename A1
>
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < A1 > >
2009-06-16 11:39:36 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( A1 ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
2009-06-16 11:39:36 +02:00
} ;
2009-06-17 06:55:18 +02:00
2009-06-16 11:39:36 +02:00
template < typename RET
, typename A1
, typename A2
>
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < A1 , A2 > >
2009-06-16 11:39:36 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( A1 , A2 ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
2009-06-16 11:39:36 +02:00
} ;
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
>
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < A1 , A2 , A3 > >
2009-06-16 11:39:36 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( A1 , A2 , A3 ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
2009-06-16 11:39:36 +02:00
} ;
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
>
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < A1 , A2 , A3 , A4 > >
2009-06-16 11:39:36 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( A1 , A2 , A3 , A4 ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
2009-06-16 11:39:36 +02:00
} ;
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
>
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < A1 , A2 , A3 , A4 , A5 > >
2009-06-16 11:39:36 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( A1 , A2 , A3 , A4 , A5 ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
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
>
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < A1 , A2 , A3 , A4 , A5 , A6 > >
2009-06-17 06:55:18 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( A1 , A2 , A3 , A4 , A5 , A6 ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
2009-06-17 06:55:18 +02:00
} ;
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
>
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < A1 , A2 , A3 , A4 , A5 , A6 , A7 > >
2009-06-16 11:39:36 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( A1 , A2 , A3 , A4 , A5 , A6 , A7 ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
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
>
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 > >
2009-06-17 06:55:18 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
2009-06-17 06:55:18 +02:00
} ;
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
>
2023-11-22 22:11:59 +01:00
struct BuildFunType < RET , Types < A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 , A9 > >
2009-06-17 06:55:18 +02:00
{
2023-11-22 22:11:59 +01:00
using Sig = RET ( A1 , A2 , A3 , A4 , A5 , A6 , A7 , A8 , A9 ) ;
using Fun = _Fun < Sig > ;
using Func = function < Sig > ;
using Functor = Func ;
2009-06-17 06:55:18 +02:00
} ;
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