'How to properly constrain an iterator based function using concepts

I have trouble understanding the concepts defined in the <iterator> header. I couldn't find good examples using them.

I tried to use the concepts in a simple function to provide better error messages. I don't understand why the output_iterator takes a type but input_iterator doesn't any. Furthermore I don't know how to make the random_assign_working function more generic.

template<typename T, std::input_iterator InputIter, std::output_iterator<T> OutputIter>
requires std::random_access_iterator<InputIter>
auto random_assign(InputIter inputBegin, InputIter inputEnd, OutputIter outBegin) {
  auto inputSize = std::distance(inputBegin, inputEnd);
  for (size_t it = 0; it < inputSize; it++) {
    auto randomIndex = rand()%inputSize;
    auto selectedInput = inputBegin[randomIndex]; // read input
    *outBegin = selectedInput; // write output
    outBegin++;
  }
}

template<std::input_iterator InputIter, std::output_iterator<uint32_t> OutputIter>
requires std::random_access_iterator<InputIter>
auto random_assign_working(InputIter inputBegin, InputIter inputEnd, OutputIter outBegin) {
  auto inputSize = std::distance(inputBegin, inputEnd);
  for (size_t it = 0; it < inputSize; it++) {
    auto randomIndex = rand()%inputSize;
    auto selectedInput = inputBegin[randomIndex]; // read input
    *outBegin = selectedInput; // write output
    outBegin++;
  }
}

int main() {
  {
    std::array<uint32_t, 9> input = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::forward_list<uint32_t> output;
    random_assign(input.begin(), input.end(), std::front_insert_iterator(output)); // how can I make this work
    random_assign_working(input.begin(), input.end(), std::front_insert_iterator(output)); // working

    std::stringstream buf {};
    buf << "Out ";
    for (auto item : output)
      buf << " " << item;
    std::cout << buf.str() << std::endl;
  }
  {
    std::array<std::string, 9> input = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
    std::vector<std::string> output;
    output.reserve(input.size());
    random_assign(input.begin(), input.end(), output.begin()); // how can I make this work
    random_assign_working(input.begin(), input.end(), std::front_insert_iterator(output)); // how can I make this work
  }
}

So my questions are: How to make use of the concepts defined in <iterator> when writing functions. How do the iterator_tags tie into this? How do I check for iterator_tags?

I would appreciate learning resources and pointing me in the right direction.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source