Home > Net >  Type deduction in C for positional information
Type deduction in C for positional information

Time:09-20

Let's assume I have a collection of functions following the following pattern:

template <typename T, typename ... Args>
T example(Args ... args, T* defaultValue);

Furthermore I have another function that operates on these collections:

template <auto Function, typename T, typename ... Args>
auto transform(Args ... args) {
    // ...
    T defaultValue /* = ... */;
    auto result = Function(args... , &defaultValue);
    // ...
    return result;
}

For example the transform function can be used like

auto result = transform<ExampleFunction, ExampleT>(int a, int b, int c);

The compiler completes the types for Args. But I have the problem that I have to specify T. However I know that T is always the last type of the parameters of Function.

Is there a way to "teach" the compiler this property so I can call the transform function without specifying T?

auto result = transform<ExampleFunction>(int a, int b, int c);

Example

In vulkan there are these functions vkEnumerateInstanceExtensionProperties and such. You always have to call these functions twice to retrieve some data. I want to create a function listify which returns this data as vector.

template <auto Function, typename T, typename ... Args>
auto listify(Args ... args)
{
    uint32_t size;
    Function(args... , &size, nullptr);
    std::vector<T> result(size);
    Function(args... , &size, result.data());
    return result;
}

I would like to call this function like so

auto result = listify<vkEnumerateInstanceExtensionProperties>(nullptr);

CodePudding user response:

You can get the parameters from function.

for example you can do something like this

#include <tuple>

template<typename F>
struct last_arg{};

template<typename ret, typename ...args>
struct last_arg<ret(*)(args...)>{
    using type = std::tuple_element_t<sizeof...(args)-1,std::tuple<args...>>;
};

template <auto F, typename ...Args>
auto f(Args... args) {
    using T=std::remove_pointer_t<typename last_arg<decltype(F)>::type>;
    T defaultValue;
    auto result = F(args... , &defaultValue);
    return result;
}

int bar(int,int*);
void foo(){
    f<bar>(1);
}

(this assumes the function is not a function object, but that's also possible)

  • Related