首页 > 解决方案 > 错误:使用通用引用的声明冲突

问题描述

我想从文章中实现通用反向功能,它适用于右值。但没有左值。

#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;    
}

我收到左值错误:

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};
      | 

你能告诉我正确解决方案的方向吗?

标签: c++templatesforwarding-reference

解决方案


首先,您不使用通用/转发参考,您只需使用普通的 R 值参考。

你想要语法template<class T> F(T&&)(构造函数必须是模板函数):

template<class F>
explicit Reverse(F&& iterable) : iterable_(std::forward<T>(iterable)){}

如果你使用 C++17 或更高版本,可以添加推导指南:

template<class T>
Reverse(T&&) -> Reverse<T>;

通过在上面添加,您不必在实例化Reverse其对象时显式指定类的模板参数。如果没有 CTAD,您需要编写:Reverse<decltype(v)>(..)处理 R 值或Reverse<decltype((v))>L 值(需要大多数内括号来获取容器的 L 值引用)。

如果你想创建临时Reverse作为v参数,只需写:

Reverse{v};

(现在为Reverse(v)您重新声明v变量)或命名实例:

Reverse withLvalue(v);

演示


推荐阅读