是否可以使用C++模板将结构上下文中的类型自动Map和转发到函数的参数?

jecbmhm3  于 2023-02-17  发布在  其他
关注(0)|答案(2)|浏览(85)

假设我有一个结构体作为数据上下文,定义如下:

struct Ctx {
   TypeA a;
   TypeB b;
   TypeC c;
   TypeD d;
   TypeE e;
};

auto TestFunc(TypeA a, TypeB b, TypeC c, args...) -> result;

并且呼叫将采取以下形式:

TestFunc(ctx.a, ctx.b, ctx.c, args...);

因为ctx是多余的,我想要一个新的 Package 器:

auto TestFunc(Ctx& ctx, args...) -> result {
    return TestFunc(ctx.a, ctx.b, ctx.c, args...);
}

有没有什么方法可以将函数的类型签名Map到结构体的类型签名,这样我就可以创建某种宏/泛型组合,而不必为访问此Ctx中成员的每个函数手动编写 Package 器?

lnlaulya

lnlaulya1#

据我所知你需要两样东西

  • 一个(或两个const)函数将结构体转换为元组:
struct Ctx {
   auto as_tuple() const { return std::tie(a, b, c, d, e); }
   auto as_tuple() { return std::tie(a, b, c, d, e); }

   TypeA a;
   TypeB b;
   TypeC c;
   TypeD d;
   TypeE e;
};

然后,假设类型是不同的,一个函数(或2以支持C省略号)从元组中只过滤出您想要的参数:

template <typename Tuple, typename Ret, typename... Ts, typename... Args>
Ret call(Ret(*func)(Ts...), Tuple&& tuple, Args&&... args)
{
    return func(std::get<Ts&>(tuple)..., std::forward<Args>(args)...);
}

template <typename Tuple, typename Ret, typename... Ts, typename... Args>
Ret call(Ret(*func)(Ts..., ...), Tuple&& tuple, Args&&... args)
{
    return func(std::get<Ts&>(tuple)..., std::forward<Args>(args)...);
}

Demo

vof42yt1

vof42yt12#

我不完全确定你想达到什么目的。
但是变量struct可能会有帮助,你可以从初始化值中推导出结构体的成员,当然其他的推导也是可能的。
我们可以在std::tuple上构建变量结构体,并且重载函数调用操作符,使用std::apply调用变量为struct的函数。
例如,参见以下解决方案:

#include <iostream>
#include <functional>
#include <tuple>

// Variadic struct
template <typename...Args>
struct Ctx {
    // Variadic data
    std::tuple<Args...> data{};  
    // Variadic Constructor. Will use CTAD
    Ctx(Args...args) : data(std::forward<decltype(args)>(args)...) {};
    // Calling the function with the data of the struct
    void operator()(std::function<void(Args...)> f) {
        std::apply(f,data);
    }
};

// Your library function
void print(int i, char c, double d) {
    std::cout << i << ' ' << c << ' ' << d << '\n';
}
// Test code
int main() {

    Ctx v(1, 'a', 1.1);
    
    v (print);
}

当然其他的实现也是可能的。如果你需要其他的东西,请评论。

相关问题