Consider the code:
#include <iostream>
#include <vector>
#include <ranges>
class TA
{
private:
int value;
public:
TA(int _value) : value(_value)
{
std::cout << "Constructor TA, value = " << value << 'n';
}
TA(const TA& a)
{
value = a.value;
std::cout << "Copy constructor TA, value = " << value << 'n';
}
TA(TA&& a) noexcept
{
value = a.value;
std::cout << "Move constructor TA, value = " << value << 'n';
}
~TA()
{
std::cout << "Destructor TA, value = " << value << 'n';
}
};
void rvalue_vector_test1()
{
std::vector a{ std::from_range, std::vector{TA(1), TA(2), TA(3), TA(4), TA(5)} };
}
void rvalue_vector_test2()
{
std::vector a{ std::from_range, std::vector{TA(1), TA(2), TA(3), TA(4), TA(5)} | std::views::as_rvalue };
}
void iota_test1()
{
std::vector a{ std::from_range,
std::views::iota(1,6) |
std::views::transform([](auto elem) {return TA(elem); }) };
}
int main()
{
rvalue_vector_test1();
rvalue_vector_test2();
iota_test1();
}
Could anybody explain why in the code:
std::vector a{ std::from_range, std::vector{TA(1), TA(2), TA(3), TA(4), TA(5)} | std::views::as_rvalue }
it is necessary to use std::views::as_rvalue
to prevent copying (although std::vector{TA(1), TA(2), TA(3), TA(4), TA(5)}
is rvalue), but in the code:
std::vector a{ std::from_range,
std::views::iota(1,6) |
std::views::transform([](auto elem) {return TA(elem); }) };
there is no need to use std::views::as_rvalue
(P.S. I know that the best way is to write:
std::vector<TA> a{ std::from_range, std::views::iota(1,6) }
– there is no copying and moving at all, but I want to know, how constructors with std::from_range
work)