std::initializer_list
can't be deduced by a template argument, which means you'll have to tell the lambda what it is explicitly:
#include <initializer_list>
#include <iostream>
#include <vector>
int main()
{
auto foo = []() -> std::initializer_list<int> { return {1, 2}; };
std::vector<int> bar{foo()};
for (int x : bar) { std::cout << x << " "; };
}
Demo. Here's the rationale behind this from the initializer list proposal:
Can an initializer list be used as a template argument? Consider:
template<class T> void f(const T&);
f({ }); // error
f({1});
f({1,2,3,4,5,6});
f({1,2.0}); // error
f(X{1,2.0}); // ok: T is X
There is obviously no problem with the last call (provided X{1,2.0} itself is valid)
because the template argument is an X. Since we are not introducing arbitrary lists of
types (product types), we cannot deduce T to be {int,double} for f({1,2.0}), so that call is
an error. Plain {} does not have a type, so f({}) is also an error.
This leaves the homogeneous lists. Should f({1}) and f({1,2,3,4,5,6}) be accepted? If so,
with what meaning? If so, the answer must be that the deduced type, T, is
initializer_list. Unless someone comes up with at least one good use of this simple
feature (a homogeneous list of elements of type E is deduced to be an
initializer_list), we won’t propose it and all the examples will be errors: No template
argument can be deduced from an (unqualified) initializer list. One reason to be cautious
here is that we can imagine someone getting confused about the possible interpretations
of single-element lists. For example, could f({1}) invoke f<int>(1)? No, that would be
quite inconsistent.
std::initializer_list
has reference semantics, therefore the thing you return would immediately dangle. – Hamner