2

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&&?)

2 Answers 2

8

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>>;
Sign up to request clarification or add additional context in comments.

Comments

0

std::make_move_iterator creates an iterator whose value type is T&&.Your old concept required T to match exactly, so sound_sample ≠ sound_sample&&.Using std::remove_cvref_t normalizes both, treating them as sound_sample.

#include <iterator>
#include <type_traits>

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

This code usess std::remove_cvref_t to ignore references and const, so both T and T&& are treated as the same underlying type.

1 Comment

This will match regular iterators, which is not what I want godbolt.org/z/b5cKvY7M1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.