如何使用 boost::json::value 调用无参数函数

How to call a parameterless function using boost::json::value

我正在修改 here 代码:

#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>
#include<iostream>
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;
  }
  int foobar()
  {
    std::cout << "I'm stupid!" << std::endl;
    return 1;
  }
};

BOOST_DESCRIBE_STRUCT(Object, (), (greet, add, foobar))

int main()
{
  Object obj;
  std::cout << call(obj, "greet", { "world" }) << std::endl;
  std::cout << call(obj, "add", { 1, 2 }) << std::endl;
  boost::json::value sc{};
  std::cout << call(obj, "add", sc) << std::endl;
}

我添加的部分是

int foobar()
{
    std::cout << "I'm stupid!" << std::endl;
    return 1;
}

boost::json::value sc{};
std::cout << call(obj, "foobar", sc) << std::endl;

输出:

error C2672: 'call_impl': no matching overloaded function found

我知道我可以添加 call_impl 的重载并将调用修改为:

  boost::mp11::mp_for_each<Fd>([&](auto D) {
    if (!found && method == D.name)
    {
      auto temp = args.as_array();
      std::cout << typeid(temp).name() << std::endl;
      if (!temp.empty())
      result = call_impl(c, D.pointer,temp );
      else
        result = call_impl(c, D.pointer);
      found = true;
    }});

我的问题是:

  1. 如何构造一个包含空值的boost::json::value,这样我就可以用它来调用那个函数

我想我已经把我的问题描述清楚了,所以我的很多尝试和操作都是错误的,不需要写,但它仍然警告我“看起来像你的post主要是代码;请添加更多详细信息。” ...

OS:windows11
IDE:visual studio2019

参数需要作为 JSON 数组传递。满足要求的最简单方法是:

std::cout << call(obj, "foobar", boost::json::array{}) << std::endl;

看到了Live On Coliru

#include <boost/describe.hpp>
#include <boost/json.hpp>
#include <boost/json/src.hpp> // for Coliru
#include <boost/mp11.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/string_view.hpp>
#include <iostream>
#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 foobar() {
        std::cout << "I'm not so stupid after all!" << std::endl;
        return 42;
    }

    int add(int x, int y) {
        return x + y;
    }
};

BOOST_DESCRIBE_STRUCT(Object, (), (greet, add, foobar))

#include <iostream>

int main() {
    Object obj;
    std::cout << call(obj, "greet", {"world"}) << std::endl;
    std::cout << call(obj, "add", {1, 2}) << std::endl;
    std::cout << call(obj, "foobar", boost::json::array{}) << std::endl;
}

版画

"Hello, world!"
3
I'm not so stupid after all!
42

当然你可以将其设置为默认参数值:Live Demo 但实际上,你只会在通用代码中使用它,而你并不知道事先说明函数没有参数。所以我认为这不会增加任何价值。