Basically I want to provide construction from const lvalue versions and rvalue reference versions:
transform_iterator(const Functor& f, const Iterator& it) :
functor(f),
iterator(it)
{}
transform_iterator(Functor&& f, Iterator&& it) :
functor(f),
iterator(it)
{}
From what I know, the rvalue reference version is not universal references. Despite that, on this call site:
template <typename InputIt, typename OutputIt>
std::pair<InputIt, OutputIt> sliding_average(InputIt first, InputIt last,
const typename std::iterator_traits<InputIt>::difference_type window_length,
OutputIt d_first)
{
using value_type = typename std::iterator_traits<InputIt>::value_type;
auto divide = [&window_length](const value_type& value)
{
return value / window_length;
};
auto iterator = shino::transformer(divide, d_first); //transform_iterator<Functor, Iterator>
shino::sliding_window(first, last, iterator, window_length);
//^^ pass by value
compiler says that rvalue reference version ends up being const lvalue reference version.
For completeness, here is the call site of the sliding_average
sliding_average(v.begin(), v.end(), window_length, output.begin());
where both v
and output
are vectors of int and doubles, and window_length
is std::size_t
.
When I remove the const lvalue version, code compiles and works correctly.
Also, this code compiles without problem with both of the constructors:
std::vector<std::string> v{"23", "25", "27"}; //just random numbers
std::vector<int> output(v.size());
auto string_to_int = [](const std::string& x)
{
return std::stoi(x);
};
auto conversion_iterator = shino::transformer(string_to_int, output.begin());
Question: How to fix it?
I think that your understanding of lvalues and rvalues is not correct.
You're not invoking transform_iterator::transform_iterator
with an rvalue anywhere in the code you've posted.
auto iterator = shino::transformer(divide, d_first);
// ^^^^^^^
// lvalue
To invoke the rvalue reference overload, you need an rvalue! std::move
can be used to cast d_first
to an rvalue reference - example:
auto iterator = shino::transformer(divide, std::move(d_first));
// ^^^^^^^^^^^^^^^^^^
// rvalue
The same applies to the code you added in your edit:
shino::sliding_window(first, last, iterator, window_length);
// ^^^^^^^^
// lvalue
You probably want:
shino::sliding_window(first, last, std::move(iterator), window_length);
// ^^^^^^^^^^^^^^^^^^^
// rvalue
Relevant questions: