2025-01-12 20:40:08 +08:00

86 lines
2.0 KiB
C++

// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe.hpp>
#include <boost/mp11.hpp>
#include <boost/json.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/string_view.hpp>
#include <stdexcept>
#include <string>
template<class C1, class C2, class R, class... A, std::size_t... I>
boost::json::value
call_impl_( C1 & c1, R (C2::*pmf)(A...), boost::json::array const & args,
std::index_sequence<I...> )
{
return boost::json::value_from(
(c1.*pmf)(
boost::json::value_to< boost::remove_cv_ref_t<A> >( args[ I ] )... ) );
}
template<class C1, class C2, class R, class... A>
boost::json::value
call_impl( C1 & c1, R (C2::*pmf)(A...), boost::json::array const & args )
{
if( args.size() != sizeof...(A) )
{
throw std::invalid_argument( "Invalid number of arguments" );
}
return call_impl_( c1, pmf, args, std::index_sequence_for<A...>() );
}
template<class C>
boost::json::value
call( C & c, boost::string_view method, boost::json::value const & args )
{
using Fd = boost::describe::describe_members<C,
boost::describe::mod_public | boost::describe::mod_function>;
bool found = false;
boost::json::value result;
boost::mp11::mp_for_each<Fd>([&](auto D){
if( !found && method == D.name)
{
result = call_impl( c, D.pointer, args.as_array() );
found = true;
}
});
if( !found )
{
throw std::invalid_argument( "Invalid method name" );
}
return result;
}
struct Object
{
std::string greet( std::string const & who )
{
return "Hello, " + who + "!";
}
int add( int x, int y )
{
return x + y;
}
};
BOOST_DESCRIBE_STRUCT(Object, (), (greet, add))
#include <iostream>
int main()
{
Object obj;
std::cout << call( obj, "greet", { "world" } ) << std::endl;
std::cout << call( obj, "add", { 1, 2 } ) << std::endl;
}