从C++函数原型创建结构

btxsgosb  于 2023-06-07  发布在  其他
关注(0)|答案(3)|浏览(210)

假设有一个C++函数foo,其原型如下:
bool foo (int a, double x, const std::vector<std::string>& v);
是否可以通过元编程自动创建一个结构类型,其属性是函数的输入参数?对于这个例子,我们将得到一个等价于以下内容的结构:

struct 
{
    int arg1; 
    double arg2; 
    std::vector<std::string> arg3;
};

我想通过A.Alexandrescu在“现代C++设计”中介绍的技术可以实现这一点,但我想知道这样的“prototype2struct”特性是否已经存在于某些库中。
为了添加更多的上下文,我从外部获取foo函数,它的原型可以是任何东西。其基本思想是封装对foo的调用,以便在另一台计算机上执行它。这意味着我需要:
1.在缓冲区中序列化调用的参数
1.发送到远程电脑上
1.以在远程计算机上执行调用。
所以我的想法是从函数原型创建一个类型,并在这个类型上使用一些序列化库。

eblbsuwk

eblbsuwk1#

您可以使用std::tuple和CTAD,如下所示:

#include <vector>
#include <string>
#include <tuple> 
bool foo (int a, double x, const std::vector<std::string>& v);

template<typename Ret, typename... Param> struct GetParamType
{
   using type = std::tuple<Param...>;
   public:
       GetParamType(Ret(*)(Param...)); 
};

struct Name
{
    decltype(GetParamType(foo))::type t;   //std::tuple of desired types   
};

Demo
请注意,这对重载函数无效。

erhoui1w

erhoui1w2#

这并不漂亮,但它是这样的:(那么,TMP是否一直都很漂亮?))

template <typename F>
struct argument_tuple {
private:
    using FT = function_traits<F>;
    static constexpr size_t arity = FT::arity;  
    template <size_t... I>
    static auto get_tuple(std::index_sequence<I...>) -> std::tuple<typename FT::template argument<I>...>;
public:
    using type = decltype(get_tuple(std::make_index_sequence<FT::arity>{}));
};

这当然依赖于function_traits meta函数。我发现boost::function_traits在这里是不够的,因为它不允许通过索引访问参数类型。
Here is a live demo
请在您将此实现用于任何严重的事情之前比我更彻底地测试它。

cx6n0qe3

cx6n0qe33#

一个只考虑自由(静态或非成员)函数的简单实现是:

template<typename>
struct arguments
{ using type = void; };

template<typename R, typename ... args>
struct arguments<R(args ...)>
{using type = std::tuple<args...>; };

template<typename F>
using arguments_t = typename arguments<T>::type;

但这不包括C变量函数&可恶的函数,以及函数指针、成员函数指针、函数对象和lambda表达式。调用约定--不是标准的--是另一个问题。
解决这个问题的一个尝试是boost.callable_traits。但这也省略了调用约定,而且太复杂了,但比依赖于MPL的boost.function_traits要好。

相关问题