In many languages, there are generators that help to initialize collections. In C++, if one wants to initialize a vector uniformly, one can write:
std::vector<int> vec(10, 42); // get 10 elements, each equals 42
What if one wants to generate different values on the fly? For example, initialize it with 10 random values, or consecutive numbers from 0 to 9? This syntax would be convenient, but it does not work in C++11:
int cnt = 0;
std::vector<int> vec(10, [&cnt]()->int { return cnt++;});
Is there a nice way to initialize a collection by iterative function calls? I currently use this ugly pattern (not much more readable/short than a loop):
std::vector<int> vec;
int cnt = 0;
std::generate_n(std::back_inserter(vec), 10, [&cnt]()->int { return cnt++;});
There is a thing that would help, and it would explain the lack of the first constructor. I can imagine an iterator that takes a function and number of calls, so that the constructor
vector ( InputIterator first, InputIterator last);
would be applicable. But I did not find anything like this in the standard library. Did I miss it? Is there another reason why the first constructor did not make it to the standard?
Best Answer
Sadly, there is no standard facility to do this.
For your specific example, you could use Boost.Iterator's
counting_iterator
like this:Or even with Boost.Range like this:
(
copy_range
will basically justreturn std::vector<int>(begin(range), end(range))
and is a great way to adopt full range construction to exisiting containers that only support range construction with two iterators.)Now, for the general purpose case with a generator function (like
std::rand
), there is thefunction_input_iterator
. When incremented, it calls the generator and saves the result, which is then returned when dereferencing it.Live example.
Sadly, since
function_input_iterator
doesn't use Boost.ResultOf, you need a function pointer or a function object type that has a nestedresult_type
. Lambdas, for whatever reason, don't have that. You could pass the lambda to astd::function
(orboost::function
) object, which defines that. Here's an example withstd::function
. One can only hope that Boost.Iterator will make use of Boost.ResultOf someday, which will usedecltype
ifBOOST_RESULT_OF_USE_DECLTYPE
is defined.