HeliumHydride
HeliumHydride

Reputation: 81

Allowing a function to accept braced initializer lists without another overload

I have a function which accepts arbitrary iterable objects/containers:

auto iterate(auto&& iterable);

And it operates on them using range-based for-loops in a generic manner.

This works fine with standard containers, C-style arrays, and std::generator, but it fails when I try to pass it an init-list:

iterate({1, 2, 3});

I get the error error: no matching function for call to ‘iterate(<brace-enclosed initializer list>) and couldn’t deduce template parameter ‘auto:57’.

How can I include initalizer lists in the considered candidates for deduction without writing a separate overload? I need it to be only one function because I also want to write iterator-based utilities that operate on multiple iterables, and I don't know how to write functions that would operate on all of them easily if I had to write multiple functions for each combination of ordinary iterable and init-list.

Upvotes: 1

Views: 108

Answers (1)

catnip
catnip

Reputation: 25388

I know you want to avoid an overload, but since you are using C++20 or later, your best option looks to be to add one that delegates to your existing function by passing it a std::span, like so:

template <class T> auto iterate
    (std::initializer_list <T> il)
{
    std::span s {il.begin (), il.end ()};
    return iterate (s);
}

A span is cheap to construct (might even be free, in this situation), but maybe adding an overload adds too much boilerplate, we don't have enough context to know.

Upvotes: 0

Related Questions