I wanted to implement universal reverse function from the article and it works for rvalue. But doesn't with lvalue.
#include <iostream>
#include <vector>
#include <functional>
template <typename T>
class Reverse
{
T iterable_;
public:
explicit Reverse(T&& iterable) : iterable_(std::forward<T>(iterable)){}
auto begin() { return std::rbegin(iterable_); }
auto end() { return std::rend(iterable_); }
};
std::vector<int> CreateVector()
{
return {0,1,2,3,4,5,6,7,8,9};
}
int main()
{
std::vector<int> v{1,2,3,4,5,6,7}; // line 23
for(const auto& i : Reverse(CreateVector()))
std::cout << i << " ";
std::cout << std::endl;
Reverse(v); // line 29
// for(const auto& i : Reverse(v))
// std::cout << i << " ";
return 0;
}
I got an error for lvalue:
main.cpp: In function 'int main()':
main.cpp:29:13: error: conflicting declaration 'Reverse<...auto...> v'
29 | Reverse(v);
| ^
main.cpp:23:22: note: previous declaration as 'std::vector<int> v'
23 | std::vector<int> v{1,2,3,4,5,6,7};
|
Can you please show me a direction to the right solution?
First, you don't use universal/forwarding reference, you just use plain R-value reference.
You want syntax template<class T> F(T&&) (constructor must be template function):
template<class F>
explicit Reverse(F&& iterable) : iterable_(std::forward<T>(iterable)){}
If you use C++17 or later, you can add deduction guide:
template<class T>
Reverse(T&&) -> Reverse<T>;
by adding above, you don't have to specify explicitly template parameter of Reverse class when instatiating its objects. Without CTAD you need to write: Reverse<decltype(v)>(..) to handle R-values, or Reverse<decltype((v))> for L-values (most inner parentheses are required to get L-value reference to container).
And if you want to create temporary Reverse taking v as argument, just write:
Reverse{v};
(now for Reverse(v) you do redeclaration of v variable) or as named instance:
Reverse withLvalue(v);
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With