Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error: conflicting declaration using universal references

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?

like image 825
IvanM Avatar asked Jul 21 '26 11:07

IvanM


1 Answers

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

like image 69
rafix07 Avatar answered Jul 24 '26 02:07

rafix07



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!