Re[7]: std::back_insert_iterator::value_type
От: Sm0ke Россия ksi
Дата: 25.07.23 10:46
Оценка: 2 (1)
Здравствуйте, пффф, Вы писали:

П>Здравствуйте, Sm0ke, Вы писали:


S>>Получить value_type можно через container_type итератора.


S>>
S>>using IterType = OutputIterator;
S>>using IterCharType = typename IterType :: container_type :: value_type;
S>>for(size_t i = 0; i < num; ++i, ++iter)
S>>{
S>>  *iter = static_cast<IterCharType>( func() );
S>>}
S>>


S>>Вот так должно работать. https://gcc.godbolt.org/z/Knfa41Tbc


П>Спасибо, но хотелось универсальный способ найти


Заглянув в описание std::void_t<> https://en.cppreference.com/w/cpp/types/void_t
я нашёл универсальное решение (аналог SFINAE) для случаев когда у итератора есть вложенный container_type, и когда его нет.

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <cstdint>
#include <type_traits>

template<typename T, typename = void>
struct iterator_trait : public std::iterator_traits<T> {};
 
template<typename T>
struct iterator_trait<
    T, std::void_t<typename T::container_type>
> : public std::iterator_traits<
    typename T::container_type::iterator
> {};

template<typename OutputIterator>
void gen_n(OutputIterator iter, size_t num, auto&& func)
{
    using IterType = OutputIterator;
    using IterCharType = iterator_trait<IterType>::value_type;
    
    for(size_t i = 0; i < num; ++i, ++iter)
    {
        *iter = static_cast<IterCharType>( func() );
    }
}

int main() {
  std::vector<char> v;
  /*std::generate_n(
    std::back_insert_iterator(v),
    std::uint8_t{10}, [n=std::uint8_t{0}]() mutable { return ++n; }
  );*/
  gen_n(std::back_insert_iterator{v}, 10
    , [n=std::uint8_t{0}]() mutable { return ++n; });
 
  for (int n : v) {
    std::cout << n << ' ';
  }
  std::cout << '\n';
  return 0;
}


тест: https://gcc.godbolt.org/z/r7qz3bKox
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.