Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a concept for a move input iterator?

I want to write a function that moves the data of a container into another container using an iterator pair.

I have the following concept:

template <typename Iter, typename T>
concept move_input_iterator = std::input_iterator<Iter> && std::same_as<std::iter_value_t<Iter>, T&&>;

And I use it like so:

template <move_input_iterator<sound_sample> Iter>
sound create_sound(const sound_details& details, Iter begin, Iter end)
{
    return sound{
        .details = details,
        .samples = {begin,end}
    };
}
sounds[sound_key] = create_sound(
    {
        .pitch_min = short(sound_info->pitch_min),
        .pitch_max = short(sound_info->pitch_max),
        .volume_min = short(sound_info->volume_min),
        .volume_max = short(sound_info->volume_max),
        .is_looped = /*TODO:*/ true,
        .radius = /*TODO:*/ 0,
    },
    std::make_move_iterator(samples.begin()),
    std::make_move_iterator(samples.end()));

(sound::samples is a std::vector<sound_sample> )

I receive the following error:

Game/src/common/sound.h:33:8: note: candidate template ignored: constraints not satisfied [with Iter = move_iterator<sound_sample *>]
   33 |         sound create_sound(const sound_details& details, Iter begin, Iter end)
      |               ^
Game/src/common/sound.h:32:12: note: because 'move_input_iterator<std::move_iterator<raid::sound_sample *>, sound_sample>' evaluated to false
   32 |         template <move_input_iterator<sound_sample> Iter>
      |                   ^
Game/src/common/iterator.h:12:61: note: because 'std::same_as<std::iter_value_t<move_iterator<sound_sample *> >, raid::sound_sample &&>' evaluated to false
   12 |         concept move_input_iterator = std::input_iterator<Iter> && std::same_as<std::iter_value_t<Iter>, T&&>;
      |                                                                    ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../include/c++/15.2.1/concepts:65:9: note: because '__detail::__same_as<raid::sound_sample, raid::sound_sample &&>' evaluated to false
   65 |       = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>;
      |         ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/15.2.1/../../../../include/c++/15.2.1/concepts:59:27: note: because 'std::is_same_v<raid::sound_sample, raid::sound_sample &&>' evaluated to false
   59 |       concept __same_as = std::is_same_v<_Tp, _Up>;

I understand the error itself, but I do not understand why std::is_same_v fails, when std::make_move_iterator is supposed to make a move iterator (which should result in a sound_sample&&?)

like image 714
Raildex Avatar asked Jan 23 '26 16:01

Raildex


1 Answers

iter_value_t always produces a cv-unqualified value type. What you need is iter_reference_t, which checks the return type of *it

template <typename Iter, typename T>
concept move_input_iterator = 
  std::input_iterator<Iter> && 
  std::same_as<std::iter_reference_t<Iter>, T&&>;

Note that move_iterator::operator*() will return ranges::iter_move(it), where it is the underlying iterator. This return value can be a prvalue in addition to an rvalue reference. So you may want to check:

template <typename Iter, typename T>
concept move_input_iterator = 
  std::input_iterator<Iter> && 
  std::same_as<std::iter_value_t<Iter>, T> &&
  std::same_as<std::iter_rvalue_reference_t<Iter>, std::iter_reference_t<Iter>>;
like image 128
康桓瑋 Avatar answered Jan 25 '26 06:01

康桓瑋



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!