I want to put objects into a container (which container is not fixed).
For that I want to use the concept std::output_iterator
.
How would I define a function that takes for example a std::insert_iterator<std::vector<T>>
and a std::insert_iterator<std::list<T>>
?
the concept std::output_iterator
takes two template arguments : I
and T
. So i am unsure how I would declare such a function.
I could do it like oldschool <algorithm>
and declare it like this:
template<typename OutIter>
void foo(OutIter writer);
but thats not that expressive imo.
UPDATE: Here is my attempt based in @RemyLebeau's answer:
#include <iterator>
#include <vector>
template<typename I, typename T, std::output_iterator<I,T> OutIter>
void foo(OutIter writer) {
writer++ = T();
}
int main() {
std::vector<int> ints;
auto inserter = std::insert_iterator(ints,ints.end());
foo(inserter);
}
@Remy Lebeau has the right idea, but not the right execution. The first template argument to a concept is the type being constrained and does not have to be specified when used to restrain another template arg.
Their answer with correct code:
#include <iterator>
#include <vector>
template<typename T, std::output_iterator<T> OutIter> // note: no template argument I required
void foo(OutIter writer) {
writer++ = T();
}
int main() {
std::vector<int> ints;
auto inserter = std::insert_iterator(ints,ints.end());
foo<int>(inserter); // note you have to specify int when calling foo
return 0;
}
This is not entirely your use-case, since you don't want to specify the type for foo's iterator when calling the function. But using the output_iterator concept, foo can specify the iterator type itself:
#include <iterator>
#include <vector>
template<std::output_iterator<int> OutIter> // Explicitly requests an iterator that ints can be written to
void foo(OutIter writer) {
writer++ = int{};
}
int main() {
std::vector<int> ints;
auto inserter = std::insert_iterator(ints,ints.end());
foo(inserter);
return 0;
}