Home > Enterprise >  Can a deducion guide put to add the right type in the template according to the accepting funcion?
Can a deducion guide put to add the right type in the template according to the accepting funcion?

Time:05-31

I have a complex problem that can be boiled down to the following deduction guide

template <class R> R return_r() { return R{}; }
void accep_float(float arg) { (void)arg; }

int main() {
  accep_float(return_r());
}

Can I put a deduction guide to make the template deduct the right type according to the accepting function, like float here accep_float(return_type<float>());?

CodePudding user response:

A templated conversion operator can be used for this kind of "backward" deduction:

struct foo {
    template <typename T>
    operator T() { return T{};}
};

void accep_float(float arg) { (void)arg; }



int main() { 
  accep_float(foo{});
}

I am not aware of deduction guides for function templates. Anyhow, you must first call foo{} (or return_r in your case) and only then the conversion to some argument type of accep_float can be done.

CodePudding user response:

This pure backwards deduction is not possible, as far as I know. However, you can figure out the parameter types of any function beforehand, and use that to pass it in manually:

namespace detail {
    template<typename R, typename... A>
    constexpr auto parameter_types(R(*)(A...)) {
        return std::tuple<A...>{};
    }
    template<typename R, typename... A>
    constexpr auto parameter_types(std::function<R(A...)>) {
        return std::tuple<A...>{};
    }
    template<typename C, typename R, typename... A>
    constexpr auto parameter_types(R(C::*)(A...)) {
        return std::tuple<A...>{};
    }
    template<typename C, typename R, typename... A>
    constexpr auto parameter_types(R(C::*)(A...) const) {
        return std::tuple<A...>{};
    }
}

template<typename F>
using parameter_types = decltype(detail::parameter_types(std::declval<F>()));

template<typename F>
using first_parameter = std::tuple_element_t<0u, parameter_types<F>>;

and now in main you can use first_parameter like this:

int main() {
    using R = first_parameter<decltype(accep_float)>;
    accep_float(return_r<R>());
}

with this method you can deduce and number of parameters, simple use std::tuple_element_t<N, parameter_types<F>>;


Now it would be neet to make some kind of apply_deduce function that will call the functions accordingly, however you can't just pass a template function name without naming it's template, therefore defeating the purpose.

Not exactly the most elegant, but since there is no other way, a macro will do the job:

#define apply_deduced(f1, f2) f1(f2<first_parameter<decltype(f1)>>())

int main() {
    apply_deduced(accep_float, return_r);
}
  • Related