1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
#include <iostream>
#include <functional>
#include <typeinfo>
#include <string>
#include <type_traits>
#include <cstring>
#ifdef __GNUG__ // GNU or compatible
#include <cxxabi.h>
#include <cstdlib>
#include <memory>
std::string demangle( const std::string& raw_name )
{
int result ;
std::unique_ptr< char, decltype(&std::free) > ptr(
__cxxabiv1::__cxa_demangle( raw_name.c_str(), nullptr, nullptr, std::addressof(result) ),
&std::free ) ;
return result == 0 ? ptr.get() : raw_name ;
}
#else
std::string demangle( const std::string& name ) { return name ; }
#endif // _GNUG_
template < typename FN >
struct extended_function : std::function<FN>
{
using base = std::function<FN> ;
using base::operator() ;
using typename base::result_type ;
using base::operator bool ;
// etc.
template < typename CALLABLE > extended_function( CALLABLE fn ) : base(fn) {}
template < typename CALLABLE > extended_function( CALLABLE fn, const std::string& n ) : base(fn), name_(n) {}
std::string target_name() const { return name_ ; }
std::string target_type() const { return demangle( base::target_type().name() ) ; }
std::string wrapper_type() const
{ return "extended_function< " + demangle( typeid(FN).name() ) + " >" ; }
std::string name_ = "" ;
};
// helper to remove the noexcept specifier from the type of a non-member function
template < typename T > struct remove_noexcept { using type = T ; } ;
template < typename R, typename... A > struct remove_noexcept< R(A...) noexcept >
{ using type = R( A... ) ; } ;
template < typename T > using remove_noexcept_t = typename remove_noexcept<T>::type;
template< typename FN >
auto make_extended_function( const FN& fn, const std::string& name )
{
using func_type = std::remove_pointer_t< remove_noexcept_t<FN> > ;
static_assert( std::is_function<func_type>::value ) ;
return extended_function<func_type>( fn, name ) ;
}
void test() { std::cout << "function void test()\n" ; }
auto plus( int a, double b, long long c ) noexcept { return a+b+c ; }
// macro for non-member functions and pointers to non-member functions (uses the default name)
#define NAMED_FN(x) make_extended_function( x, #x )
int main()
{
const auto t = make_extended_function( test, "this is the non-member function test" ) ;
std::cout << "name: " << t.target_name()
<< "\nwrapper type: " << t.wrapper_type()
<< "\ntarget type: " << t.target_type() << '\n' ;
t() ;
const auto t1 = NAMED_FN(test) ; // use macro (name is the name of he function)
std::cout << "\nname: " << t1.target_name()
<< "\nwrapper type: " << t1.wrapper_type()
<< "\ntarget type: " << t1.target_type() << '\n' ;
t1() ;
const auto p = make_extended_function( plus, "a custom name for plus" ) ;
std::cout << "\n\nname: " << p.target_name()
<< "\nwrapper type: " << p.wrapper_type()
<< "\ntarget type: " << p.target_type() << '\n'
<< "p(1,2.3,4) returned " << p(1,2.3,4) << '\n' ;
const auto p1 = NAMED_FN(plus) ; // use macro (name is the name of he function)
std::cout << "\nname: " << p1.target_name()
<< "\nwrapper type: " << p1.wrapper_type()
<< "\ntarget type: " << p1.target_type() << '\n'
<< "p1(1,2.3,4) returned " << p1(1,2.3,4) << '\n' ;
}
| |