#include #include #include #include VkInstance foo; template struct fn_traits : public fn_traits::operator())> {}; template struct fn_traits : public fn_traits {}; template struct fn_traits : public fn_traits {}; template struct fn_traits : public fn_traits {}; template struct fn_traits { using return_t = Ret; template using argn_t = std::tuple_element_t>; }; struct _ct {} _c; struct _dt {} _d; template struct pack_type_index { template static constexpr std::size_t value(std::index_sequence) { auto l = {std::is_same_v * Indices...}; return std::accumulate(l.begin(), l.end(), 0); } static constexpr std::size_t value() { return value(std::index_sequence_for{}); } }; template , bool = std::is_same_v> struct ResolveArg; // _c template struct ResolveArg { static constexpr auto Resolve(T& o, uint32_t *c, OutType *d) { return c; } }; // _d template struct ResolveArg { static constexpr auto Resolve(T& o, uint32_t *c, OutType *d) { return d; } }; // passthrough template struct ResolveArg { static constexpr auto Resolve(T& o, uint32_t *c, OutType *d) { return o; } }; template VkResult invoke_helper(uint32_t *c, OutType *d, F &f, TTuple &tt, std::index_sequence) { return std::invoke(f, ResolveArg, OutType>::Resolve(std::get(tt), c, d)...); } template struct VkEnumFnWrapper { using IdxSeq = std::index_sequence_for; using KOutType = fn_traits::template argn_t...>::value()>; using OutType = std::remove_pointer_t; using TypeTuple = std::tuple...>; using FnType = std::decay_t; FnType fn; TypeTuple tt; public: explicit VkEnumFnWrapper(F &&f, Types&&... t) { tt = std::forward_as_tuple(t...); fn = f; } VkResult operator()(uint32_t *c, OutType *d) { return invoke_helper(c, d, fn, tt, IdxSeq{}); } VkResult Cheese(uint32_t *c, OutType *d) { return VK_SUCCESS; } }; template VkEnumFnWrapper wrap(F &&f, Types&&... t) { return VkEnumFnWrapper(std::forward(f), std::forward(t)...); } template auto UtilVkEnumerate(F &&f) { using OutType = std::remove_pointer_t::template argn_t<1>>; uint32_t c; if(f(&c, nullptr) != VK_SUCCESS) throw std::runtime_error{""}; std::vector Result(c); if(f(&c, Result.data()) != VK_SUCCESS) throw std::runtime_error{""}; return Result; } int main() { //auto l = wrap(vkEnumeratePhysicalDevices, foo, _c, _d); auto l = UtilVkEnumerate(wrap(vkEnumerateInstanceExtensionProperties, nullptr, _c, _d)); for(const auto &p : l) { std::cout << p.extensionName << std::endl; } return 0; }