Home > OS >  C passing a callback with a range parameter
C passing a callback with a range parameter

Time:12-23

I'd like to achieve something like this:

void mycallback(auto v)
{
    for (auto x : v) {
        std::cout << x << '\n';
    }
}

void f(auto cb) {
    cb(std::vector<int>{44,55,66});
    cb(std::vector<int>{123, 234, 345} | std::ranges::views::drop(1));
}

void run()
{
    f(mycallback);
    f([](auto v) {
        for (auto x : v) {
            std::cout << x << '\n';
        }
    });
}

mycallback() should accept a C 20 range of integers. To be more specific I'll need owning_view with miscellaneous filters. So it is a template. I need to pass this callback to f() which can call the callback with different range types. I need it to accept mainly lambdas. The f() can't be instantiated because compiler doesn't know how to deduce the type since the callback instantiation is required inside the f() function.

test.cpp:34:6: note:   template argument deduction/substitution failed:
test.cpp:41:6: note:   couldn’t deduce template parameter ‘auto:25’
   41 |     f(mycallback);

Is there some lazy instantiation option?

CodePudding user response:

You could pass a lambda that calls the callback.

And for the callback to work with ranges, change the signature to auto&& v, so that it can accept r-value references as arguments.

[Demo]

#include <iostream>
#include <ranges>
#include <vector>

void mycallback(auto&& v) {
    for (auto x : v) {
        std::cout << x << " ";
    }
    std::cout << "\n";
}

void f(auto cb) {
    cb(std::vector<int>{44, 55, 66});
    cb(std::vector<int>{123, 234, 345} | std::ranges::views::drop(1));
}

int main() {
    f([](auto&& v) { return mycallback(v); });
}

CodePudding user response:

mycallback is very similar to function template due to the auto parameter.
And in this line:

f(mycallback);

The compiler doesn't know with which type (for the auto parameter) to instantiate it.

Instead you can make it a functor - i.e. a class with operator().
You can also make the call operator accept v bv const & for types that will otherwise be copied.

Example:

#include <vector>
#include <iostream>
#include <ranges>

class mycallback
{
public:
    void operator()(auto const& v) const
    {
        for (auto const& x : v) {
            std::cout << x << '\n';
        }
    }
};

void f(auto cb) {
    cb(std::vector<int>{44, 55, 66});
    cb(std::vector<int>{123, 234, 345} | std::ranges::views::drop(1));
}

int main()
{
    f(mycallback{});
}

Output:

44
55
66
234
345
  • Related