2

I have created a example my current problem. I want to be able to able to call the following function without specifying the template type since the compiler should be able to find out the type:

template<typename T, class Iterable>
void foreach1(std::function<void(T&)> action, Iterable& iterable) {
    std::cout << typeid(T).name() << std::endl;
    for (auto& data : iterable)
        action(data);
}

If i call the function this way:

std::vector<int> a = { 1, 2, 3 };
foreach1([](int& data) {
    std::cout << data << std::endl;
}, a);

I get an error. I know that i could fix the problem by replacing std::function with a template the following way:

template<class Action, class Iterable>
void foreach2(Action action, Iterable& iterable) {
//std::cout << typeid(T).name() << std::endl; // no access to T
for (auto& data : iterable)
    action(data);
}

But by doing that i lose access to the type T. Is there a way of keeping access to the type T and be able to use template argument deduction?

Dolfos
  • 58
  • 7
  • Does this answer your question? [Failure to deduce template argument std::function from lambda function](https://stackoverflow.com/questions/53326206/failure-to-deduce-template-argument-stdfunction-from-lambda-function) – Fureeish Jan 14 '20 at 23:29

1 Answers1

3

Implicit conversions are not allowed when passing arguments to parameters whose types depend on deduced template parameters.

I suggest using the second option:

template<class Action, class Iterable>
void foreach2(Action action, Iterable& iterable)

And to determine T, start with making a std::function out of action:

std::function(action)

Then write a template to get the type of the parameter of a std::function:

template <typename T> struct std_func_param {};
template <typename R, typename T> struct std_func_param<std::function<R(T)>> {using type = T;};
template <typename T> using std_func_param_t = typename std_func_param<T>::type;

Use it like this:

using T = std_func_param_t<decltype(std::function(action))>;
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • Is there a runtime cost in converting a lambda to a std::function? I have read in some places not to use std::function in most cases. Is this one case where you have to use it? – Dolfos Jan 14 '20 at 23:42
  • 1
    @Dolfos There might be a runtime cost, but in this case `std::function(action)` is only used inside of `decltype()`, which means it's not evaluated. No actual `std::function` is constructed. – HolyBlackCat Jan 14 '20 at 23:43
  • How come there might be a runtime cost when it's not evaluated? – Dolfos Jan 14 '20 at 23:44
  • @Dolfos I mean there would probably be a runtime cost if `std::function(action)` was evaluated. Since it's not, there is no extra cost. – HolyBlackCat Jan 14 '20 at 23:44
  • Does the compiler optimize the construction of std::function away because decltype() does not count as "using" the variable? – Dolfos Jan 14 '20 at 23:47
  • @Dolfos Yes, it's required to. – HolyBlackCat Jan 14 '20 at 23:48
  • Thank you for your answers. – Dolfos Jan 14 '20 at 23:49