#include <iostream>
#include <functional>
#include <tuple>
#include <type_traits>
#include <vector>
using namespace std;
#include <functional>
#include <tuple>
#include <type_traits>
using namespace std;
#include <stdio.h>
#include <string.h>
template < typename T, typename U, std:: enable_if_t < std:: is_same < T, U> :: value , int > = 0 >
T convert_type( U _in)
{
//return const_cast<U>(_in);
return _in;
}
template < typename T, typename U, std:: enable_if_t < std:: is_same < T, std:: add_const_t < U>> :: value , int > = 0 >
T convert_type( U _in)
{
//return const_cast<U>(_in);
return _in;
}
// these conversion functions only can convert type to pointer to type, else return reference to type, so they're a bit limited
// pointer to pointer, or
template < typename T, typename U, std:: enable_if_t < std:: is_same < T, std:: add_const_t < U>> :: value , int > = 0 >
T& convert_type( U& _in)
{
return _in;
}
template < typename T, typename U, std:: enable_if_t < std:: is_same < T, std:: add_lvalue_reference_t < U>> :: value , int > = 0 >
T& convert_type( U& _in)
{
return _in;
}
template < typename T, typename U, std:: enable_if_t < std:: is_same < T, std:: add_lvalue_reference_t < std:: add_const_t < U>>> :: value , int > = 0 >
T& convert_type( U& _in)
{
return _in;
}
// for conversion to pointer
//T&* to T*
template < typename T, typename U, std:: enable_if_t < std:: is_same < T, std:: add_pointer_t < U>> :: value , int > = 0 >
T convert_type( U& _in)
{
return std:: addressof ( _in) ;
}
template < typename T, typename U, std:: enable_if_t < std:: is_same < T, std:: add_const_t < U>> :: value , int > = 0 >
T convert_type( U& _in)
{
return std:: addressof ( _in) ;
}
template < typename T, typename U, std:: enable_if_t < std:: is_same < T, std:: add_pointer_t < std:: add_const_t < U>>> :: value , int > = 0 >
T convert_type( U& _in)
{
return std:: addressof ( _in) ;
}
template < typename T>
struct function_traits;
template < typename R, typename ...Args >
struct function_traits< std:: function < R( Args...) >>
{
static const size_t nargs = sizeof ...( Args) ;
typedef R result_type;
template < size_t i>
struct arg
{
typedef typename std:: tuple_element < i, std:: tuple < Args...>> :: type type;
} ;
static const bool isGlobalOrStaticContainer = true ;
static const bool isClassContainer = false ;
static const bool isPointerContainer = false ;
static const bool isConstInClassContainer = false ;
static const bool returnsVoid = std:: is_same < R, void > :: value ;
} ;
template < typename C, typename R, typename ...Args >
struct function_traits< std:: function < R( * C:: * ) ( Args...) >>
{
static const size_t nargs = sizeof ...( Args) ;
typedef R result_type;
template < size_t i>
struct arg
{
typedef typename std:: tuple_element < i, std:: tuple < Args...>> :: type type;
} ;
static const bool isGlobalOrStaticContainer = false ;
static const bool isClassContainer = false ;
static const bool isPointerContainer = true ;
static const bool isConstInClassContainer = false ;
static const bool returnsVoid = std:: is_same < R, void > :: value ;
} ;
template < typename C, typename R, typename ...Args >
struct function_traits< std:: function < R( C:: * ) ( Args...) >>
{
static const size_t nargs = sizeof ...( Args) ;
typedef R result_type;
template < size_t i>
struct arg
{
typedef typename std:: tuple_element < i, std:: tuple < Args...>> :: type type;
} ;
static const bool isGlobalOrStaticContainer = false ;
static const bool isClassContainer = true ;
static const bool isPointerContainer = false ;
static const bool isConstInClassContainer = false ;
static const bool returnsVoid = std:: is_same < R, void > :: value ;
} ;
template < typename C, typename R, typename ...Args >
struct function_traits< std:: function < R( C:: * ) ( Args...) const >>
{
static const size_t nargs = sizeof ...( Args) ;
typedef R result_type;
template < size_t i>
struct arg
{
typedef typename std:: tuple_element < i, std:: tuple < Args...>> :: type type;
} ;
static const bool isGlobalOrStaticContainer = false ;
static const bool isClassContainer = true ;
static const bool isPointerContainer = false ;
static const bool isConstInClassContainer = true ;
static const bool returnsVoid = std:: is_same < R, void > :: value ;
} ;
template < typename ParamType> class Param
{
public :
typedef ParamType Type;
static const bool isOut = false ;
} ;
template < typename ParamType> class ParamOut : public Param< ParamType>
{
public :
static const bool isOut = true ;
} ;
template < typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ParamType, size_t paramIndex, typename ... ParamTypes >
static bool UnwrapParameter( unsigned argc, std:: vector < void * > & args, typename ParamType:: Type & ppt)
{
if ( argc > paramIndex)
{
ppt = * ( ( std:: add_pointer_t < typename ParamType:: Type > ( args[ paramIndex] ) ) ) ;
}
return true ;
}
template < typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ... ParamType , size_t ... paramIndex >
static bool UnwrapParameters( unsigned argc, std:: vector < void * > & args, std:: tuple < typename ParamType:: Type ...> & params, std:: index_sequence < paramIndex...> )
{
bool r[ ] = { true , UnwrapParameter< Type, ReturnType, MethodType, Method, ParamType, paramIndex, ParamType...> ( argc, args, std:: get < paramIndex> ( params) ) ... } ;
bool res = true ;
for ( size_t i = 0 ; i < sizeof ...( ParamType) + 1 && res == true ; i++ )
res & = r[ i] ;
return res;
}
template < typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ... ParamType >
static bool UnwrapParameters( unsigned argc, std:: vector < void * > & args, std:: tuple < typename ParamType:: Type ...> & params)
{
return UnwrapParameters< Type, ReturnType, MethodType, Method, ParamType...> ( argc, args, params, std:: make_index_sequence < sizeof ...( ParamType) > { } ) ;
}
template < typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ParamType, size_t paramIndex, typename ... ParamTypes >
static bool WrapParameter( unsigned argc, std:: vector < void * > & args, typename ParamType:: Type & ppt)
{
if ( ParamType:: isOut && ( argc > paramIndex) )
{
// Wrap them back - nothing to do here, in this example
}
return true ;
}
template < typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ... ParamType , size_t ... paramIndex >
static bool WrapParameters( unsigned argc, std:: vector < void * > & args, std:: tuple < typename ParamType:: Type ...> & params, std:: index_sequence < paramIndex...> )
{
bool r[ ] = { true , WrapParameter< Type, ReturnType, MethodType, Method, ParamType, paramIndex, ParamType...> ( argc, args, std:: get < paramIndex> ( params) ) ... } ;
bool res = true ;
for ( size_t i = 0 ; i < sizeof ...( ParamType) + 1 && res == true ; i++ )
res & = r[ i] ;
return res;
}
template < typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ... ParamType >
static bool WrapParameters( unsigned argc, std:: vector < void * > & args, std:: tuple < typename ParamType:: Type ...> & params)
{
return WrapParameters< Type, ReturnType, MethodType, Method, ParamType...> ( argc, args, params, std:: make_index_sequence < sizeof ...( ParamType) > { } ) ;
}
template < typename Type, typename ReturnType, typename MethodType,
typename std:: enable_if < function_traits< std:: function < typename std:: remove_pointer < MethodType> :: type >> :: isPointerContainer , MethodType> :: type Method,
typename ... ParamType , size_t ... paramIndex >
static ReturnType CallMethodRet( bool & success, Type* obj, std:: tuple < typename ParamType:: Type ...> & params, std:: index_sequence < paramIndex...> )
{
if ( ! ( obj && ( obj- > * Method) ) )
success = false ;
return ( obj- > * Method) ( convert_type< typename function_traits< std:: function < typename std:: remove_pointer < MethodType> :: type >> :: template arg< paramIndex> :: type , typename ParamType:: Type > ( std:: get < paramIndex> ( params) ) ...) ;
}
template < typename Type, typename ReturnType, typename MethodType,
typename std:: enable_if < function_traits< std:: function < typename std:: remove_pointer < MethodType> :: type >> :: isGlobalOrStaticContainer , MethodType> :: type Method,
typename ... ParamType , size_t ... paramIndex >
static ReturnType CallMethodRet( bool & success, Type* obj, std:: tuple < typename ParamType:: Type ...> & params, std:: index_sequence < paramIndex...> )
{
if ( ! ( * Method) )
success = false ;
return ( * Method) ( convert_type< typename function_traits< std:: function < typename std:: remove_pointer < MethodType> :: type >> :: template arg< paramIndex> :: type , typename ParamType:: Type > ( std:: get < paramIndex> ( params) ) ...) ;
}
template < typename Type, typename ReturnType, typename MethodType,
typename std:: enable_if < function_traits< std:: function < typename std:: remove_pointer < MethodType> :: type >> :: isClassContainer , MethodType> :: type Method,
typename ... ParamType , size_t ... paramIndex >
static ReturnType CallMethodRet( bool & success, Type* obj, std:: tuple < typename ParamType:: Type ...> & params, std:: index_sequence < paramIndex...> )
{
if ( ! ( obj && ( Method) ) )
success = false ;
return ( obj- > * Method) ( convert_type< typename function_traits< std:: function < typename std:: remove_pointer < MethodType> :: type >> :: template arg< paramIndex> :: type , typename ParamType:: Type > ( std:: get < paramIndex> ( params) ) ...) ;
}
template < typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ... ParamType >
static ReturnType CallMethodRet( bool & success, Type* obj, std:: tuple < typename ParamType:: Type ...> & params)
{
return CallMethodRet< Type, ReturnType, MethodType, Method, ParamType...> ( success, obj, params, std:: make_index_sequence < sizeof ...( ParamType) > { } ) ;
}
template < typename Type, typename ReturnType, typename MethodType,
typename std:: enable_if < ! function_traits< std:: function < typename std:: remove_pointer < MethodType> :: type >> :: returnsVoid , MethodType> :: type Method,
typename ... ParamType >
static bool ExecuteMethod( Type* obj, unsigned argc, std:: vector < void * > & args, ReturnType& result)
{
try
{
const unsigned numArgs = sizeof ...( ParamType) ;
std:: tuple < typename ParamType:: Type ...> params = std:: make_tuple ( typename ParamType:: Type ( ) ...) ;
if ( ! UnwrapParameters< Type, ReturnType, MethodType, Method, ParamType...> ( argc, args, params) )
return false ;
bool success = true ;
result = CallMethodRet< Type, ReturnType, MethodType, Method, ParamType...> ( success, obj, params) ;
if ( ! success)
return false ; // Throw method not found here
if ( ! WrapParameters< Type, ReturnType, MethodType, Method, ParamType...> ( argc, args, params) )
return false ;
}
catch ( ...)
{
// whatever...
}
return true ;
}
template < typename Type, typename ReturnType, typename MethodType,
typename std:: enable_if < function_traits< std:: function < typename std:: remove_pointer < MethodType> :: type >> :: returnsVoid , MethodType> :: type Method,
typename ... ParamType >
static bool ExecuteMethod( Type* obj, unsigned argc, std:: vector < void * > & args)
{
try
{
const unsigned numArgs = sizeof ...( ParamType) ;
std:: tuple < typename ParamType:: Type ...> params = std:: make_tuple ( typename ParamType:: Type ( ) ...) ;
if ( ! UnwrapParameters< Type, ReturnType, MethodType, Method, ParamType...> ( argc, args, params) )
return false ;
bool success = true ;
CallMethodRet< Type, ReturnType, MethodType, Method, ParamType...> ( success, obj, params) ;
if ( ! success)
return false ; // Throw method not found here
if ( ! WrapParameters< Type, ReturnType, MethodType, Method, ParamType...> ( argc, args, params) )
return false ;
}
catch ( ...)
{
// whatever...
}
return true ;
}
class O
{
public :
void func( int a, string b, bool & c, const char * d)
{
std:: cout << "Successfully called func with in values " << a << "," << b << "," << c << " and " << d << std:: endl ;
c = true ;
std:: cout << "Successfully called func with out values " << a << "," << b << "," << c << " and " << d << std:: endl ;
}
int func_i( int a, string b, bool & c, const char * d)
{
std:: cout << "Successfully called func with in values " << a << "," << b << "," << c << " and " << d << std:: endl ;
c = false ;
std:: cout << "Successfully called func with out values " << a << "," << b << "," << c << " and " << d << std:: endl ;
return 1 ;
}
} ;
int main( ) {
int a = 1 ;
string b = "string" ;
bool c = false ;
char * d = new char [ sizeof "char*" ] ;
strcpy ( d, "char*" ) ;
std:: vector < void * > v { ( void * ) & a, ( void * ) & b, ( void * ) & c, ( void * ) & d} ;
std:: cout << std:: endl ;
O o;
std:: cout << ExecuteMethod< O, void , void ( O:: * ) ( int , string, bool & , const char * ) , & O:: func , Param< int > , Param< string> , ParamOut< bool > , Param< char * >> ( & o, v.size ( ) , v) ; // with Param<const char*> is compiling, but I need to pass Param<char*>
std:: cout << std:: endl << std:: endl ;
int result = 0 ;
std:: cout << ExecuteMethod< O, int , int ( O:: * ) ( int , string, bool & , const char * ) , & O:: func_i , Param< int > , Param< string> , ParamOut< bool > , Param< char * >> ( & o, v.size ( ) , v, result) << std:: endl ; // with Param<const char*> is compiling Param<char*>
std:: cout << result << std:: endl ;
delete [ ] d;
return 0 ;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KI2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CiNpbmNsdWRlIDx2ZWN0b3I+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KI2luY2x1ZGUgPHR1cGxlPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgojaW5jbHVkZSA8c3RkaW8uaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVSwgc3RkOjplbmFibGVfaWZfdDxzdGQ6OmlzX3NhbWU8VCwgVT46OnZhbHVlLCBpbnQ+ID0gMD4KVCBjb252ZXJ0X3R5cGUoVSBfaW4pCnsKICAgIC8vcmV0dXJuIGNvbnN0X2Nhc3Q8VT4oX2luKTsKICAgIHJldHVybiBfaW47Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFUsIHN0ZDo6ZW5hYmxlX2lmX3Q8c3RkOjppc19zYW1lPFQsIHN0ZDo6YWRkX2NvbnN0X3Q8VT4+Ojp2YWx1ZSwgaW50PiA9IDA+ClQgY29udmVydF90eXBlKFUgX2luKQp7CiAgICAvL3JldHVybiBjb25zdF9jYXN0PFU+KF9pbik7CiAgICByZXR1cm4gX2luOwp9CgoKLy8gdGhlc2UgY29udmVyc2lvbiBmdW5jdGlvbnMgb25seSBjYW4gY29udmVydCB0eXBlIHRvIHBvaW50ZXIgdG8gdHlwZSwgZWxzZSByZXR1cm4gcmVmZXJlbmNlIHRvIHR5cGUsIHNvIHRoZXkncmUgYSBiaXQgbGltaXRlZAovLyBwb2ludGVyIHRvIHBvaW50ZXIsIG9yCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFUsIHN0ZDo6ZW5hYmxlX2lmX3Q8c3RkOjppc19zYW1lPFQsIHN0ZDo6YWRkX2NvbnN0X3Q8VT4+Ojp2YWx1ZSwgaW50PiA9IDA+ClQmIGNvbnZlcnRfdHlwZShVJiBfaW4pCnsKICAgIHJldHVybiBfaW47Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFUsIHN0ZDo6ZW5hYmxlX2lmX3Q8c3RkOjppc19zYW1lPFQsIHN0ZDo6YWRkX2x2YWx1ZV9yZWZlcmVuY2VfdDxVPj46OnZhbHVlLCBpbnQ+ID0gMD4KVCYgY29udmVydF90eXBlKFUmIF9pbikKewogICAgcmV0dXJuIF9pbjsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgVCwgdHlwZW5hbWUgVSwgc3RkOjplbmFibGVfaWZfdDxzdGQ6OmlzX3NhbWU8VCwgc3RkOjphZGRfbHZhbHVlX3JlZmVyZW5jZV90PHN0ZDo6YWRkX2NvbnN0X3Q8VT4+Pjo6dmFsdWUsIGludD4gPSAwPgpUJiBjb252ZXJ0X3R5cGUoVSYgX2luKQp7CiAgICByZXR1cm4gX2luOwp9CgoKLy8gZm9yIGNvbnZlcnNpb24gdG8gcG9pbnRlcgovL1QmKiB0byBUKgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBVLCBzdGQ6OmVuYWJsZV9pZl90PHN0ZDo6aXNfc2FtZTxULCBzdGQ6OmFkZF9wb2ludGVyX3Q8VT4+Ojp2YWx1ZSwgaW50PiA9IDA+ClQgY29udmVydF90eXBlKFUmIF9pbikKewogICAgcmV0dXJuIHN0ZDo6YWRkcmVzc29mKF9pbik7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFUsIHN0ZDo6ZW5hYmxlX2lmX3Q8c3RkOjppc19zYW1lPFQsIHN0ZDo6YWRkX2NvbnN0X3Q8VT4+Ojp2YWx1ZSwgaW50PiA9IDA+ClQgY29udmVydF90eXBlKFUmIF9pbikKewogICAgcmV0dXJuIHN0ZDo6YWRkcmVzc29mKF9pbik7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFUsIHN0ZDo6ZW5hYmxlX2lmX3Q8c3RkOjppc19zYW1lPFQsIHN0ZDo6YWRkX3BvaW50ZXJfdDxzdGQ6OmFkZF9jb25zdF90PFU+Pj46OnZhbHVlLCBpbnQ+ID0gMD4KVCBjb252ZXJ0X3R5cGUoVSYgX2luKQp7CiAgICByZXR1cm4gc3RkOjphZGRyZXNzb2YoX2luKTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgVD4Kc3RydWN0IGZ1bmN0aW9uX3RyYWl0czsKCnRlbXBsYXRlPHR5cGVuYW1lIFIsIHR5cGVuYW1lIC4uLkFyZ3M+CnN0cnVjdCBmdW5jdGlvbl90cmFpdHM8c3RkOjpmdW5jdGlvbjxSKEFyZ3MuLi4pPj4KewogICAgc3RhdGljIGNvbnN0IHNpemVfdCBuYXJncyA9IHNpemVvZi4uLihBcmdzKTsKCiAgICB0eXBlZGVmIFIgcmVzdWx0X3R5cGU7CgogICAgdGVtcGxhdGUgPHNpemVfdCBpPgogICAgc3RydWN0IGFyZwogICAgewogICAgICAgIHR5cGVkZWYgdHlwZW5hbWUgc3RkOjp0dXBsZV9lbGVtZW50PGksIHN0ZDo6dHVwbGU8QXJncy4uLj4+Ojp0eXBlIHR5cGU7CiAgICB9OwoKICAgIHN0YXRpYyBjb25zdCBib29sIGlzR2xvYmFsT3JTdGF0aWNDb250YWluZXIgPSB0cnVlOwogICAgc3RhdGljIGNvbnN0IGJvb2wgaXNDbGFzc0NvbnRhaW5lciA9IGZhbHNlOwogICAgc3RhdGljIGNvbnN0IGJvb2wgaXNQb2ludGVyQ29udGFpbmVyID0gZmFsc2U7CiAgICBzdGF0aWMgY29uc3QgYm9vbCBpc0NvbnN0SW5DbGFzc0NvbnRhaW5lciA9IGZhbHNlOwogICAgc3RhdGljIGNvbnN0IGJvb2wgcmV0dXJuc1ZvaWQgPSBzdGQ6OmlzX3NhbWU8Uiwgdm9pZD46OnZhbHVlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgQywgdHlwZW5hbWUgUiwgdHlwZW5hbWUgLi4uQXJncz4Kc3RydWN0IGZ1bmN0aW9uX3RyYWl0czxzdGQ6OmZ1bmN0aW9uPFIoKkM6OiopKEFyZ3MuLi4pPj4KewogICAgc3RhdGljIGNvbnN0IHNpemVfdCBuYXJncyA9IHNpemVvZi4uLihBcmdzKTsKCiAgICB0eXBlZGVmIFIgcmVzdWx0X3R5cGU7CgogICAgdGVtcGxhdGUgPHNpemVfdCBpPgogICAgc3RydWN0IGFyZwogICAgewogICAgICAgIHR5cGVkZWYgdHlwZW5hbWUgc3RkOjp0dXBsZV9lbGVtZW50PGksIHN0ZDo6dHVwbGU8QXJncy4uLj4+Ojp0eXBlIHR5cGU7CiAgICB9OwoKICAgIHN0YXRpYyBjb25zdCBib29sIGlzR2xvYmFsT3JTdGF0aWNDb250YWluZXIgPSBmYWxzZTsKICAgIHN0YXRpYyBjb25zdCBib29sIGlzQ2xhc3NDb250YWluZXIgPSBmYWxzZTsKICAgIHN0YXRpYyBjb25zdCBib29sIGlzUG9pbnRlckNvbnRhaW5lciA9IHRydWU7CiAgICBzdGF0aWMgY29uc3QgYm9vbCBpc0NvbnN0SW5DbGFzc0NvbnRhaW5lciA9IGZhbHNlOwogICAgc3RhdGljIGNvbnN0IGJvb2wgcmV0dXJuc1ZvaWQgPSBzdGQ6OmlzX3NhbWU8Uiwgdm9pZD46OnZhbHVlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgQywgdHlwZW5hbWUgUiwgdHlwZW5hbWUgLi4uQXJncz4Kc3RydWN0IGZ1bmN0aW9uX3RyYWl0czxzdGQ6OmZ1bmN0aW9uPFIoQzo6KikoQXJncy4uLik+Pgp7CiAgICBzdGF0aWMgY29uc3Qgc2l6ZV90IG5hcmdzID0gc2l6ZW9mLi4uKEFyZ3MpOwoKICAgIHR5cGVkZWYgUiByZXN1bHRfdHlwZTsKCiAgICB0ZW1wbGF0ZSA8c2l6ZV90IGk+CiAgICBzdHJ1Y3QgYXJnCiAgICB7CiAgICAgICAgdHlwZWRlZiB0eXBlbmFtZSBzdGQ6OnR1cGxlX2VsZW1lbnQ8aSwgc3RkOjp0dXBsZTxBcmdzLi4uPj46OnR5cGUgdHlwZTsKICAgIH07CgogICAgc3RhdGljIGNvbnN0IGJvb2wgaXNHbG9iYWxPclN0YXRpY0NvbnRhaW5lciA9IGZhbHNlOwogICAgc3RhdGljIGNvbnN0IGJvb2wgaXNDbGFzc0NvbnRhaW5lciA9IHRydWU7CiAgICBzdGF0aWMgY29uc3QgYm9vbCBpc1BvaW50ZXJDb250YWluZXIgPSBmYWxzZTsKICAgIHN0YXRpYyBjb25zdCBib29sIGlzQ29uc3RJbkNsYXNzQ29udGFpbmVyID0gZmFsc2U7CiAgICBzdGF0aWMgY29uc3QgYm9vbCByZXR1cm5zVm9pZCA9IHN0ZDo6aXNfc2FtZTxSLCB2b2lkPjo6dmFsdWU7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBDLCB0eXBlbmFtZSBSLCB0eXBlbmFtZSAuLi5BcmdzPgpzdHJ1Y3QgZnVuY3Rpb25fdHJhaXRzPHN0ZDo6ZnVuY3Rpb248UihDOjoqKShBcmdzLi4uKSBjb25zdD4+CnsKICAgIHN0YXRpYyBjb25zdCBzaXplX3QgbmFyZ3MgPSBzaXplb2YuLi4oQXJncyk7CgogICAgdHlwZWRlZiBSIHJlc3VsdF90eXBlOwoKICAgIHRlbXBsYXRlIDxzaXplX3QgaT4KICAgIHN0cnVjdCBhcmcKICAgIHsKICAgICAgICB0eXBlZGVmIHR5cGVuYW1lIHN0ZDo6dHVwbGVfZWxlbWVudDxpLCBzdGQ6OnR1cGxlPEFyZ3MuLi4+Pjo6dHlwZSB0eXBlOwogICAgfTsKCiAgICBzdGF0aWMgY29uc3QgYm9vbCBpc0dsb2JhbE9yU3RhdGljQ29udGFpbmVyID0gZmFsc2U7CiAgICBzdGF0aWMgY29uc3QgYm9vbCBpc0NsYXNzQ29udGFpbmVyID0gdHJ1ZTsKICAgIHN0YXRpYyBjb25zdCBib29sIGlzUG9pbnRlckNvbnRhaW5lciA9IGZhbHNlOwogICAgc3RhdGljIGNvbnN0IGJvb2wgaXNDb25zdEluQ2xhc3NDb250YWluZXIgPSB0cnVlOwogICAgc3RhdGljIGNvbnN0IGJvb2wgcmV0dXJuc1ZvaWQgPSBzdGQ6OmlzX3NhbWU8Uiwgdm9pZD46OnZhbHVlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgUGFyYW1UeXBlPiBjbGFzcyBQYXJhbQp7CnB1YmxpYzoKCiAgICB0eXBlZGVmIFBhcmFtVHlwZSBUeXBlOwoKICAgIHN0YXRpYyBjb25zdCBib29sIGlzT3V0ID0gZmFsc2U7Cn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBQYXJhbVR5cGU+IGNsYXNzIFBhcmFtT3V0IDogcHVibGljIFBhcmFtPFBhcmFtVHlwZT4KewpwdWJsaWM6CgogICAgc3RhdGljIGNvbnN0IGJvb2wgaXNPdXQgPSB0cnVlOwp9OwoKdGVtcGxhdGU8dHlwZW5hbWUgVHlwZSwgdHlwZW5hbWUgUmV0dXJuVHlwZSwgdHlwZW5hbWUgTWV0aG9kVHlwZSwgTWV0aG9kVHlwZSBNZXRob2QsIHR5cGVuYW1lIFBhcmFtVHlwZSwgc2l6ZV90IHBhcmFtSW5kZXgsIHR5cGVuYW1lLi4uIFBhcmFtVHlwZXM+CnN0YXRpYyBib29sIFVud3JhcFBhcmFtZXRlcih1bnNpZ25lZCBhcmdjLCBzdGQ6OnZlY3Rvcjx2b2lkKj4mIGFyZ3MsIHR5cGVuYW1lIFBhcmFtVHlwZTo6VHlwZSAmcHB0KQp7CiAgICBpZiAoYXJnYyA+IHBhcmFtSW5kZXgpCiAgICB7CiAgICAgICAgcHB0ID0gKigoc3RkOjphZGRfcG9pbnRlcl90PHR5cGVuYW1lIFBhcmFtVHlwZTo6VHlwZT4oYXJnc1twYXJhbUluZGV4XSkpKTsKICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgVHlwZSwgdHlwZW5hbWUgUmV0dXJuVHlwZSwgdHlwZW5hbWUgTWV0aG9kVHlwZSwgTWV0aG9kVHlwZSBNZXRob2QsIHR5cGVuYW1lLi4uIFBhcmFtVHlwZSwgc2l6ZV90Li4uIHBhcmFtSW5kZXg+CnN0YXRpYyBib29sIFVud3JhcFBhcmFtZXRlcnModW5zaWduZWQgYXJnYywgc3RkOjp2ZWN0b3I8dm9pZCo+JiBhcmdzLCBzdGQ6OnR1cGxlPHR5cGVuYW1lIFBhcmFtVHlwZTo6VHlwZS4uLj4mIHBhcmFtcywgc3RkOjppbmRleF9zZXF1ZW5jZTxwYXJhbUluZGV4Li4uPikKewogICAgYm9vbCByW10gPSB7IHRydWUsIFVud3JhcFBhcmFtZXRlcjxUeXBlLCBSZXR1cm5UeXBlLCBNZXRob2RUeXBlLCBNZXRob2QsIFBhcmFtVHlwZSwgcGFyYW1JbmRleCwgUGFyYW1UeXBlLi4uPihhcmdjLCBhcmdzLCBzdGQ6OmdldDxwYXJhbUluZGV4PihwYXJhbXMpKS4uLiB9OwoKICAgIGJvb2wgcmVzID0gdHJ1ZTsKICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgc2l6ZW9mLi4uKFBhcmFtVHlwZSkgKyAxICYmIHJlcyA9PSB0cnVlOyBpKyspCiAgICAgICAgcmVzICY9IHJbaV07CiAgICByZXR1cm4gcmVzOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUeXBlLCB0eXBlbmFtZSBSZXR1cm5UeXBlLCB0eXBlbmFtZSBNZXRob2RUeXBlLCBNZXRob2RUeXBlIE1ldGhvZCwgdHlwZW5hbWUuLi4gUGFyYW1UeXBlPgpzdGF0aWMgYm9vbCBVbndyYXBQYXJhbWV0ZXJzKHVuc2lnbmVkIGFyZ2MsIHN0ZDo6dmVjdG9yPHZvaWQqPiYgYXJncywgc3RkOjp0dXBsZTx0eXBlbmFtZSBQYXJhbVR5cGU6OlR5cGUuLi4+JiBwYXJhbXMpCnsKICAgIHJldHVybiBVbndyYXBQYXJhbWV0ZXJzPFR5cGUsIFJldHVyblR5cGUsIE1ldGhvZFR5cGUsIE1ldGhvZCwgUGFyYW1UeXBlLi4uPihhcmdjLCBhcmdzLCBwYXJhbXMsIHN0ZDo6bWFrZV9pbmRleF9zZXF1ZW5jZTxzaXplb2YuLi4oUGFyYW1UeXBlKT57fSk7Cn0KCgp0ZW1wbGF0ZTx0eXBlbmFtZSBUeXBlLCB0eXBlbmFtZSBSZXR1cm5UeXBlLCB0eXBlbmFtZSBNZXRob2RUeXBlLCBNZXRob2RUeXBlIE1ldGhvZCwgdHlwZW5hbWUgUGFyYW1UeXBlLCBzaXplX3QgcGFyYW1JbmRleCwgdHlwZW5hbWUuLi4gUGFyYW1UeXBlcz4Kc3RhdGljIGJvb2wgV3JhcFBhcmFtZXRlcih1bnNpZ25lZCBhcmdjLCBzdGQ6OnZlY3Rvcjx2b2lkKj4mIGFyZ3MsIHR5cGVuYW1lIFBhcmFtVHlwZTo6VHlwZSAmcHB0KQp7CiAgICBpZiAoUGFyYW1UeXBlOjppc091dCAmJiAoYXJnYyA+IHBhcmFtSW5kZXgpKQogICAgewogICAgICAgIC8vIFdyYXAgdGhlbSBiYWNrIC0gbm90aGluZyB0byBkbyBoZXJlLCBpbiB0aGlzIGV4YW1wbGUKICAgIH0KCiAgICByZXR1cm4gdHJ1ZTsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgVHlwZSwgdHlwZW5hbWUgUmV0dXJuVHlwZSwgdHlwZW5hbWUgTWV0aG9kVHlwZSwgTWV0aG9kVHlwZSBNZXRob2QsIHR5cGVuYW1lLi4uIFBhcmFtVHlwZSwgc2l6ZV90Li4uIHBhcmFtSW5kZXg+CnN0YXRpYyBib29sIFdyYXBQYXJhbWV0ZXJzKHVuc2lnbmVkIGFyZ2MsIHN0ZDo6dmVjdG9yPHZvaWQqPiYgYXJncywgc3RkOjp0dXBsZTx0eXBlbmFtZSBQYXJhbVR5cGU6OlR5cGUuLi4+JiBwYXJhbXMsIHN0ZDo6aW5kZXhfc2VxdWVuY2U8cGFyYW1JbmRleC4uLj4pCnsKICAgIGJvb2wgcltdID0geyB0cnVlLCBXcmFwUGFyYW1ldGVyPFR5cGUsIFJldHVyblR5cGUsIE1ldGhvZFR5cGUsIE1ldGhvZCwgUGFyYW1UeXBlLCBwYXJhbUluZGV4LCBQYXJhbVR5cGUuLi4+KGFyZ2MsIGFyZ3MsIHN0ZDo6Z2V0PHBhcmFtSW5kZXg+KHBhcmFtcykpLi4uIH07CgogICAgYm9vbCByZXMgPSB0cnVlOwogICAgZm9yIChzaXplX3QgaSA9IDA7IGkgPCBzaXplb2YuLi4oUGFyYW1UeXBlKSsxICYmIHJlcyA9PSB0cnVlOyBpKyspCiAgICAgICAgcmVzICY9IHJbaV07CiAgICByZXR1cm4gcmVzOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUeXBlLCB0eXBlbmFtZSBSZXR1cm5UeXBlLCB0eXBlbmFtZSBNZXRob2RUeXBlLCBNZXRob2RUeXBlIE1ldGhvZCwgdHlwZW5hbWUuLi4gUGFyYW1UeXBlPgpzdGF0aWMgYm9vbCBXcmFwUGFyYW1ldGVycyh1bnNpZ25lZCBhcmdjLCBzdGQ6OnZlY3Rvcjx2b2lkKj4mIGFyZ3MsIHN0ZDo6dHVwbGU8dHlwZW5hbWUgUGFyYW1UeXBlOjpUeXBlLi4uPiYgcGFyYW1zKQp7CiAgICByZXR1cm4gV3JhcFBhcmFtZXRlcnM8VHlwZSwgUmV0dXJuVHlwZSwgTWV0aG9kVHlwZSwgTWV0aG9kLCBQYXJhbVR5cGUuLi4+KGFyZ2MsIGFyZ3MsIHBhcmFtcywgc3RkOjptYWtlX2luZGV4X3NlcXVlbmNlPHNpemVvZi4uLihQYXJhbVR5cGUpPnt9KTsKfQoKCnRlbXBsYXRlPHR5cGVuYW1lIFR5cGUsIHR5cGVuYW1lIFJldHVyblR5cGUsIHR5cGVuYW1lIE1ldGhvZFR5cGUsCiAgICB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxmdW5jdGlvbl90cmFpdHM8c3RkOjpmdW5jdGlvbjx0eXBlbmFtZSBzdGQ6OnJlbW92ZV9wb2ludGVyPE1ldGhvZFR5cGU+Ojp0eXBlPj46OmlzUG9pbnRlckNvbnRhaW5lciwgTWV0aG9kVHlwZT46OnR5cGUgTWV0aG9kLAogICAgdHlwZW5hbWUuLi4gUGFyYW1UeXBlLCBzaXplX3QuLi4gcGFyYW1JbmRleD4KICAgIHN0YXRpYyBSZXR1cm5UeXBlIENhbGxNZXRob2RSZXQoYm9vbCYgc3VjY2VzcywgVHlwZSogb2JqLCBzdGQ6OnR1cGxlPHR5cGVuYW1lIFBhcmFtVHlwZTo6VHlwZS4uLj4mIHBhcmFtcywgc3RkOjppbmRleF9zZXF1ZW5jZTxwYXJhbUluZGV4Li4uPikKewogICAgaWYgKCEob2JqICYmIChvYmotPipNZXRob2QpKSkKICAgICAgICBzdWNjZXNzID0gZmFsc2U7CgogICAgcmV0dXJuIChvYmotPipNZXRob2QpKGNvbnZlcnRfdHlwZTx0eXBlbmFtZSBmdW5jdGlvbl90cmFpdHM8c3RkOjpmdW5jdGlvbjx0eXBlbmFtZSBzdGQ6OnJlbW92ZV9wb2ludGVyPE1ldGhvZFR5cGU+Ojp0eXBlPj46OnRlbXBsYXRlIGFyZzxwYXJhbUluZGV4Pjo6dHlwZSwgdHlwZW5hbWUgUGFyYW1UeXBlOjpUeXBlPihzdGQ6OmdldDxwYXJhbUluZGV4PihwYXJhbXMpKS4uLik7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFR5cGUsIHR5cGVuYW1lIFJldHVyblR5cGUsIHR5cGVuYW1lIE1ldGhvZFR5cGUsCiAgICB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxmdW5jdGlvbl90cmFpdHM8c3RkOjpmdW5jdGlvbjx0eXBlbmFtZSBzdGQ6OnJlbW92ZV9wb2ludGVyPE1ldGhvZFR5cGU+Ojp0eXBlPj46OmlzR2xvYmFsT3JTdGF0aWNDb250YWluZXIsIE1ldGhvZFR5cGU+Ojp0eXBlIE1ldGhvZCwKICAgIHR5cGVuYW1lLi4uIFBhcmFtVHlwZSwgc2l6ZV90Li4uIHBhcmFtSW5kZXg+CiAgICBzdGF0aWMgUmV0dXJuVHlwZSBDYWxsTWV0aG9kUmV0KGJvb2wmIHN1Y2Nlc3MsIFR5cGUqIG9iaiwgc3RkOjp0dXBsZTx0eXBlbmFtZSBQYXJhbVR5cGU6OlR5cGUuLi4+JiBwYXJhbXMsIHN0ZDo6aW5kZXhfc2VxdWVuY2U8cGFyYW1JbmRleC4uLj4pCnsKICAgIGlmICghKCpNZXRob2QpKQogICAgICAgIHN1Y2Nlc3MgPSBmYWxzZTsKCiAgICByZXR1cm4gKCpNZXRob2QpKGNvbnZlcnRfdHlwZTx0eXBlbmFtZSBmdW5jdGlvbl90cmFpdHM8c3RkOjpmdW5jdGlvbjx0eXBlbmFtZSBzdGQ6OnJlbW92ZV9wb2ludGVyPE1ldGhvZFR5cGU+Ojp0eXBlPj46OnRlbXBsYXRlIGFyZzxwYXJhbUluZGV4Pjo6dHlwZSwgdHlwZW5hbWUgUGFyYW1UeXBlOjpUeXBlPihzdGQ6OmdldDxwYXJhbUluZGV4PihwYXJhbXMpKS4uLik7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFR5cGUsIHR5cGVuYW1lIFJldHVyblR5cGUsIHR5cGVuYW1lIE1ldGhvZFR5cGUsCiAgICB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxmdW5jdGlvbl90cmFpdHM8c3RkOjpmdW5jdGlvbjx0eXBlbmFtZSBzdGQ6OnJlbW92ZV9wb2ludGVyPE1ldGhvZFR5cGU+Ojp0eXBlPj46OmlzQ2xhc3NDb250YWluZXIsIE1ldGhvZFR5cGU+Ojp0eXBlIE1ldGhvZCwKICAgIHR5cGVuYW1lLi4uIFBhcmFtVHlwZSwgc2l6ZV90Li4uIHBhcmFtSW5kZXg+CiAgICBzdGF0aWMgUmV0dXJuVHlwZSBDYWxsTWV0aG9kUmV0KGJvb2wmIHN1Y2Nlc3MsIFR5cGUqIG9iaiwgc3RkOjp0dXBsZTx0eXBlbmFtZSBQYXJhbVR5cGU6OlR5cGUuLi4+JiBwYXJhbXMsIHN0ZDo6aW5kZXhfc2VxdWVuY2U8cGFyYW1JbmRleC4uLj4pCnsKICAgIGlmICghKG9iaiAmJiAoTWV0aG9kKSkpCiAgICAgICAgc3VjY2VzcyA9IGZhbHNlOwoKICAgIHJldHVybiAob2JqLT4qTWV0aG9kKShjb252ZXJ0X3R5cGU8dHlwZW5hbWUgZnVuY3Rpb25fdHJhaXRzPHN0ZDo6ZnVuY3Rpb248dHlwZW5hbWUgc3RkOjpyZW1vdmVfcG9pbnRlcjxNZXRob2RUeXBlPjo6dHlwZT4+Ojp0ZW1wbGF0ZSBhcmc8cGFyYW1JbmRleD46OnR5cGUsIHR5cGVuYW1lIFBhcmFtVHlwZTo6VHlwZT4oc3RkOjpnZXQ8cGFyYW1JbmRleD4ocGFyYW1zKSkuLi4pOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVHlwZSwgdHlwZW5hbWUgUmV0dXJuVHlwZSwgdHlwZW5hbWUgTWV0aG9kVHlwZSwgTWV0aG9kVHlwZSBNZXRob2QsIHR5cGVuYW1lLi4uIFBhcmFtVHlwZT4Kc3RhdGljIFJldHVyblR5cGUgQ2FsbE1ldGhvZFJldChib29sJiBzdWNjZXNzLCBUeXBlKiBvYmosIHN0ZDo6dHVwbGU8dHlwZW5hbWUgUGFyYW1UeXBlOjpUeXBlLi4uPiYgcGFyYW1zKQp7CiAgICByZXR1cm4gQ2FsbE1ldGhvZFJldDxUeXBlLCBSZXR1cm5UeXBlLCBNZXRob2RUeXBlLCBNZXRob2QsIFBhcmFtVHlwZS4uLj4oc3VjY2Vzcywgb2JqLCBwYXJhbXMsIHN0ZDo6bWFrZV9pbmRleF9zZXF1ZW5jZTxzaXplb2YuLi4oUGFyYW1UeXBlKT57fSk7Cn0KCgp0ZW1wbGF0ZTx0eXBlbmFtZSBUeXBlLCB0eXBlbmFtZSBSZXR1cm5UeXBlLCB0eXBlbmFtZSBNZXRob2RUeXBlLAogICAgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8IWZ1bmN0aW9uX3RyYWl0czxzdGQ6OmZ1bmN0aW9uPHR5cGVuYW1lIHN0ZDo6cmVtb3ZlX3BvaW50ZXI8TWV0aG9kVHlwZT46OnR5cGU+Pjo6cmV0dXJuc1ZvaWQsIE1ldGhvZFR5cGU+Ojp0eXBlIE1ldGhvZCwKICAgIHR5cGVuYW1lLi4uIFBhcmFtVHlwZT4Kc3RhdGljIGJvb2wgRXhlY3V0ZU1ldGhvZChUeXBlKiBvYmosIHVuc2lnbmVkIGFyZ2MsIHN0ZDo6dmVjdG9yPHZvaWQqPiYgYXJncywgUmV0dXJuVHlwZSYgcmVzdWx0KQp7CiAgICB0cnkKICAgIHsKICAgICAgICBjb25zdCB1bnNpZ25lZCBudW1BcmdzID0gc2l6ZW9mLi4uKFBhcmFtVHlwZSk7CgogICAgICAgIHN0ZDo6dHVwbGU8dHlwZW5hbWUgUGFyYW1UeXBlOjpUeXBlLi4uPiBwYXJhbXMgPSBzdGQ6Om1ha2VfdHVwbGUodHlwZW5hbWUgUGFyYW1UeXBlOjpUeXBlKCkuLi4pOwoKICAgICAgICBpZiAoIVVud3JhcFBhcmFtZXRlcnM8VHlwZSwgUmV0dXJuVHlwZSwgTWV0aG9kVHlwZSwgTWV0aG9kLCBQYXJhbVR5cGUuLi4+KGFyZ2MsIGFyZ3MsIHBhcmFtcykpCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKCiAgICAgICAgYm9vbCBzdWNjZXNzID0gdHJ1ZTsKCiAgICAgICAgcmVzdWx0ID0gQ2FsbE1ldGhvZFJldDxUeXBlLCBSZXR1cm5UeXBlLCBNZXRob2RUeXBlLCBNZXRob2QsIFBhcmFtVHlwZS4uLj4oc3VjY2Vzcywgb2JqLCBwYXJhbXMpOwoKICAgICAgICBpZiAoIXN1Y2Nlc3MpCiAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBUaHJvdyBtZXRob2Qgbm90IGZvdW5kIGhlcmUKCiAgICAgICAgaWYgKCFXcmFwUGFyYW1ldGVyczxUeXBlLCBSZXR1cm5UeXBlLCBNZXRob2RUeXBlLCBNZXRob2QsIFBhcmFtVHlwZS4uLj4oYXJnYywgYXJncywgcGFyYW1zKSkKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgY2F0Y2ggKC4uLikKICAgIHsKICAgICAgICAvLyB3aGF0ZXZlci4uLgogICAgfQoKICAgIHJldHVybiB0cnVlOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUeXBlLCB0eXBlbmFtZSBSZXR1cm5UeXBlLCB0eXBlbmFtZSBNZXRob2RUeXBlLAogICAgdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8ZnVuY3Rpb25fdHJhaXRzPHN0ZDo6ZnVuY3Rpb248dHlwZW5hbWUgc3RkOjpyZW1vdmVfcG9pbnRlcjxNZXRob2RUeXBlPjo6dHlwZT4+OjpyZXR1cm5zVm9pZCwgTWV0aG9kVHlwZT46OnR5cGUgTWV0aG9kLAogICAgdHlwZW5hbWUuLi4gUGFyYW1UeXBlPgogICAgc3RhdGljIGJvb2wgRXhlY3V0ZU1ldGhvZChUeXBlKiBvYmosIHVuc2lnbmVkIGFyZ2MsIHN0ZDo6dmVjdG9yPHZvaWQqPiYgYXJncykKewogICAgdHJ5CiAgICB7CiAgICAgICAgY29uc3QgdW5zaWduZWQgbnVtQXJncyA9IHNpemVvZi4uLihQYXJhbVR5cGUpOwoKICAgICAgICBzdGQ6OnR1cGxlPHR5cGVuYW1lIFBhcmFtVHlwZTo6VHlwZS4uLj4gcGFyYW1zID0gc3RkOjptYWtlX3R1cGxlKHR5cGVuYW1lIFBhcmFtVHlwZTo6VHlwZSgpLi4uKTsKCiAgICAgICAgaWYgKCFVbndyYXBQYXJhbWV0ZXJzPFR5cGUsIFJldHVyblR5cGUsIE1ldGhvZFR5cGUsIE1ldGhvZCwgUGFyYW1UeXBlLi4uPihhcmdjLCBhcmdzLCBwYXJhbXMpKQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CgogICAgICAgIGJvb2wgc3VjY2VzcyA9IHRydWU7CgogICAgICAgIENhbGxNZXRob2RSZXQ8VHlwZSwgUmV0dXJuVHlwZSwgTWV0aG9kVHlwZSwgTWV0aG9kLCBQYXJhbVR5cGUuLi4+KHN1Y2Nlc3MsIG9iaiwgcGFyYW1zKTsKCiAgICAgICAgaWYgKCFzdWNjZXNzKQogICAgICAgICAgICByZXR1cm4gZmFsc2U7IC8vIFRocm93IG1ldGhvZCBub3QgZm91bmQgaGVyZQoKICAgICAgICBpZiAoIVdyYXBQYXJhbWV0ZXJzPFR5cGUsIFJldHVyblR5cGUsIE1ldGhvZFR5cGUsIE1ldGhvZCwgUGFyYW1UeXBlLi4uPihhcmdjLCBhcmdzLCBwYXJhbXMpKQogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBjYXRjaCAoLi4uKQogICAgewogICAgICAgIC8vIHdoYXRldmVyLi4uCiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKfQoKY2xhc3MgTyAKewpwdWJsaWM6CiAgICB2b2lkIGZ1bmMoaW50IGEsIHN0cmluZyBiLCBib29sJiBjLCBjb25zdCBjaGFyKiBkKQogICAgewogICAgICAgIHN0ZDo6Y291dCA8PCAiU3VjY2Vzc2Z1bGx5IGNhbGxlZCBmdW5jIHdpdGggaW4gdmFsdWVzICIgPDwgYSA8PCAiLCIgPDwgYiA8PCAiLCIgPDwgYyA8PCAiIGFuZCAiIDw8IGQgPDwgc3RkOjplbmRsOwoKICAgICAgICBjID0gdHJ1ZTsKCiAgICAgICAgc3RkOjpjb3V0IDw8ICJTdWNjZXNzZnVsbHkgY2FsbGVkIGZ1bmMgd2l0aCBvdXQgdmFsdWVzICIgPDwgYSA8PCAiLCIgPDwgYiA8PCAiLCIgPDwgYyA8PCAiIGFuZCAiIDw8IGQgPDwgc3RkOjplbmRsOwogICAgfQoKICAgIGludCBmdW5jX2koaW50IGEsIHN0cmluZyBiLCBib29sJiBjLCBjb25zdCBjaGFyKiBkKQogICAgewogICAgICAgIHN0ZDo6Y291dCA8PCAiU3VjY2Vzc2Z1bGx5IGNhbGxlZCBmdW5jIHdpdGggaW4gdmFsdWVzICIgPDwgYSA8PCAiLCIgPDwgYiA8PCAiLCIgPDwgYyA8PCAiIGFuZCAiIDw8IGQgPDwgc3RkOjplbmRsOwoKICAgICAgICBjID0gZmFsc2U7CgogICAgICAgIHN0ZDo6Y291dCA8PCAiU3VjY2Vzc2Z1bGx5IGNhbGxlZCBmdW5jIHdpdGggb3V0IHZhbHVlcyAiIDw8IGEgPDwgIiwiIDw8IGIgPDwgIiwiIDw8IGMgPDwgIiBhbmQgIiA8PCBkIDw8IHN0ZDo6ZW5kbDsKCiAgICAgICAgcmV0dXJuIDE7CiAgICB9Cn07CgppbnQgbWFpbigpIHsKCiAgICBpbnQgYSA9IDE7CiAgICBzdHJpbmcgYiA9ICJzdHJpbmciOwogICAgYm9vbCBjID0gZmFsc2U7CiAgICBjaGFyKiBkID0gbmV3IGNoYXJbc2l6ZW9mICJjaGFyKiJdOwoJc3RyY3B5KGQsICJjaGFyKiIpOwoJCiAgICBzdGQ6OnZlY3Rvcjx2b2lkKj4gdiB7KHZvaWQqKSZhLCAodm9pZCopJmIsICh2b2lkKikmYywgKHZvaWQqKSZkfTsKCiAgICBzdGQ6OmNvdXQgPDwgc3RkOjplbmRsOwoKICAgIE8gbzsKCiAgICBzdGQ6OmNvdXQgPDwgRXhlY3V0ZU1ldGhvZDxPLCB2b2lkLCB2b2lkKE86OiopKGludCwgc3RyaW5nLCBib29sJiwgY29uc3QgY2hhciopLCAmTzo6ZnVuYywgUGFyYW08aW50PiwgUGFyYW08c3RyaW5nPiwgUGFyYW1PdXQ8Ym9vbD4sIFBhcmFtPGNoYXIqPj4oJm8sIHYuc2l6ZSgpLCB2KTsgLy8gd2l0aCBQYXJhbTxjb25zdCBjaGFyKj4gaXMgY29tcGlsaW5nLCBidXQgSSBuZWVkIHRvIHBhc3MgUGFyYW08Y2hhcio+CgogICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbCA8PCBzdGQ6OmVuZGw7CgogICAgaW50IHJlc3VsdCA9IDA7CiAgICBzdGQ6OmNvdXQgPDwgRXhlY3V0ZU1ldGhvZDxPLCBpbnQsIGludChPOjoqKShpbnQsIHN0cmluZywgYm9vbCYsIGNvbnN0IGNoYXIqKSwgJk86OmZ1bmNfaSwgUGFyYW08aW50PiwgUGFyYW08c3RyaW5nPiwgUGFyYW1PdXQ8Ym9vbD4sIFBhcmFtPGNoYXIqPj4oJm8sIHYuc2l6ZSgpLCB2LCByZXN1bHQpIDw8IHN0ZDo6ZW5kbDsgLy8gd2l0aCBQYXJhbTxjb25zdCBjaGFyKj4gaXMgY29tcGlsaW5nIFBhcmFtPGNoYXIqPgogICAgc3RkOjpjb3V0IDw8IHJlc3VsdCA8PCBzdGQ6OmVuZGw7CgkKCWRlbGV0ZVtdIGQ7CgkKICAgIHJldHVybiAwOwp9
compilation info
prog.cpp: In instantiation of 'ReturnType CallMethodRet(bool&, Type*, std::tuple<typename ParamType::Type ...>&, std::index_sequence<paramIndex ...>) [with Type = O; ReturnType = void; MethodType = void (O::*)(int, std::basic_string<char>, bool&, const char*); typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type> >::isClassContainer, MethodType>::type Method = &O::func; ParamType = Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>; unsigned int ...paramIndex = 0u, 1u, 2u, 3u; std::index_sequence<paramIndex ...> = std::integer_sequence<unsigned int, 0u, 1u, 2u, 3u>]':
prog.cpp:265:77: required from 'ReturnType CallMethodRet(bool&, Type*, std::tuple<typename ParamType::Type ...>&) [with Type = O; ReturnType = void; MethodType = void (O::*)(int, std::basic_string<char>, bool&, const char*); MethodType Method = &O::func; ParamType = {Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>}]'
prog.cpp:317:74: required from 'bool ExecuteMethod(Type*, unsigned int, std::vector<void*>&) [with Type = O; ReturnType = void; MethodType = void (O::*)(int, std::basic_string<char>, bool&, const char*); typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type> >::returnsVoid, MethodType>::type Method = &O::func; ParamType = {Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>}]'
prog.cpp:370:168: required from here
prog.cpp:259:186: error: no matching function for call to 'convert_type(char*&)'
return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
^
prog.cpp:17:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same< <template-parameter-1-1>, <template-parameter-1-2> >::value, int>::type <anonymous> > T convert_type(U)
T convert_type(U _in)
^
prog.cpp:17:3: note: template argument deduction/substitution failed:
prog.cpp:16:85: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, U>::value, int> = 0>
^
prog.cpp:16:85: note: invalid template non-type parameter
prog.cpp:24:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T convert_type(U)
T convert_type(U _in)
^
prog.cpp:24:3: note: template argument deduction/substitution failed:
prog.cpp:23:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
^
prog.cpp:23:103: note: invalid template non-type parameter
prog.cpp:34:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T& convert_type(U&)
T& convert_type(U& _in)
^
prog.cpp:34:4: note: template argument deduction/substitution failed:
prog.cpp:33:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
^
prog.cpp:33:103: note: invalid template non-type parameter
prog.cpp:40:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_lvalue_reference<U>::type>::value, int>::type <anonymous> > T& convert_type(U&)
T& convert_type(U& _in)
^
prog.cpp:40:4: note: template argument deduction/substitution failed:
prog.cpp:39:114: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<U>>::value, int> = 0>
^
prog.cpp:39:114: note: invalid template non-type parameter
prog.cpp:46:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_lvalue_reference<typename std::add_const<U>::type>::type>::value, int>::type <anonymous> > T& convert_type(U&)
T& convert_type(U& _in)
^
prog.cpp:46:4: note: template argument deduction/substitution failed:
prog.cpp:45:132: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<std::add_const_t<U>>>::value, int> = 0>
^
prog.cpp:45:132: note: invalid template non-type parameter
prog.cpp:55:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_pointer<U>::type>::value, int>::type <anonymous> > T convert_type(U&)
T convert_type(U& _in)
^
prog.cpp:55:3: note: template argument deduction/substitution failed:
prog.cpp:54:105: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<U>>::value, int> = 0>
^
prog.cpp:54:105: note: invalid template non-type parameter
prog.cpp:61:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T convert_type(U&)
T convert_type(U& _in)
^
prog.cpp:61:3: note: template argument deduction/substitution failed:
prog.cpp:60:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
^
prog.cpp:60:103: note: invalid template non-type parameter
prog.cpp:67:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_pointer<typename std::add_const<U>::type>::type>::value, int>::type <anonymous> > T convert_type(U&)
T convert_type(U& _in)
^
prog.cpp:67:3: note: template argument deduction/substitution failed:
prog.cpp:66:123: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<std::add_const_t<U>>>::value, int> = 0>
^
prog.cpp:66:123: note: invalid template non-type parameter
prog.cpp:259:219: error: return-statement with a value, in function returning 'void' [-fpermissive]
return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
^
prog.cpp: In instantiation of 'ReturnType CallMethodRet(bool&, Type*, std::tuple<typename ParamType::Type ...>&, std::index_sequence<paramIndex ...>) [with Type = O; ReturnType = int; MethodType = int (O::*)(int, std::basic_string<char>, bool&, const char*); typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type> >::isClassContainer, MethodType>::type Method = &O::func_i; ParamType = Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>; unsigned int ...paramIndex = 0u, 1u, 2u, 3u; std::index_sequence<paramIndex ...> = std::integer_sequence<unsigned int, 0u, 1u, 2u, 3u>]':
prog.cpp:265:77: required from 'ReturnType CallMethodRet(bool&, Type*, std::tuple<typename ParamType::Type ...>&) [with Type = O; ReturnType = int; MethodType = int (O::*)(int, std::basic_string<char>, bool&, const char*); MethodType Method = &O::func_i; ParamType = {Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>}]'
prog.cpp:285:83: required from 'bool ExecuteMethod(Type*, unsigned int, std::vector<void*>&, ReturnType&) [with Type = O; ReturnType = int; MethodType = int (O::*)(int, std::basic_string<char>, bool&, const char*); typename std::enable_if<(! function_traits<std::function<typename std::remove_pointer<MethodType>::type> >::returnsVoid), MethodType>::type Method = &O::func_i; ParamType = {Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>}]'
prog.cpp:375:176: required from here
prog.cpp:259:186: error: no matching function for call to 'convert_type(char*&)'
return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
^
prog.cpp:17:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same< <template-parameter-1-1>, <template-parameter-1-2> >::value, int>::type <anonymous> > T convert_type(U)
T convert_type(U _in)
^
prog.cpp:17:3: note: template argument deduction/substitution failed:
prog.cpp:16:85: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, U>::value, int> = 0>
^
prog.cpp:16:85: note: invalid template non-type parameter
prog.cpp:24:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T convert_type(U)
T convert_type(U _in)
^
prog.cpp:24:3: note: template argument deduction/substitution failed:
prog.cpp:23:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
^
prog.cpp:23:103: note: invalid template non-type parameter
prog.cpp:34:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T& convert_type(U&)
T& convert_type(U& _in)
^
prog.cpp:34:4: note: template argument deduction/substitution failed:
prog.cpp:33:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
^
prog.cpp:33:103: note: invalid template non-type parameter
prog.cpp:40:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_lvalue_reference<U>::type>::value, int>::type <anonymous> > T& convert_type(U&)
T& convert_type(U& _in)
^
prog.cpp:40:4: note: template argument deduction/substitution failed:
prog.cpp:39:114: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<U>>::value, int> = 0>
^
prog.cpp:39:114: note: invalid template non-type parameter
prog.cpp:46:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_lvalue_reference<typename std::add_const<U>::type>::type>::value, int>::type <anonymous> > T& convert_type(U&)
T& convert_type(U& _in)
^
prog.cpp:46:4: note: template argument deduction/substitution failed:
prog.cpp:45:132: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<std::add_const_t<U>>>::value, int> = 0>
^
prog.cpp:45:132: note: invalid template non-type parameter
prog.cpp:55:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_pointer<U>::type>::value, int>::type <anonymous> > T convert_type(U&)
T convert_type(U& _in)
^
prog.cpp:55:3: note: template argument deduction/substitution failed:
prog.cpp:54:105: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<U>>::value, int> = 0>
^
prog.cpp:54:105: note: invalid template non-type parameter
prog.cpp:61:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T convert_type(U&)
T convert_type(U& _in)
^
prog.cpp:61:3: note: template argument deduction/substitution failed:
prog.cpp:60:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
^
prog.cpp:60:103: note: invalid template non-type parameter
prog.cpp:67:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_pointer<typename std::add_const<U>::type>::type>::value, int>::type <anonymous> > T convert_type(U&)
T convert_type(U& _in)
^
prog.cpp:67:3: note: template argument deduction/substitution failed:
prog.cpp:66:123: error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<std::add_const_t<U>>>::value, int> = 0>
^
prog.cpp:66:123: note: invalid template non-type parameter
stdout