【问题标题】:Perfect forwarding for returned value?返回值的完美转发?
【发布时间】:2020-05-21 10:04:27
【问题描述】:

我正在重载operator[]

const Type&& operator[](int index) const {
        if (index >= size) { std::cout << "Error: excessive index.\n"; return 0; }
        else if (index < 0) { std::cout << "Error: negative index.\n"; return 0; }
        else {
            Node* temp = head->next;
            for (int i = 0; i < index; i++) { temp = temp->next; }
            return temp->value;
        }
    }

但我需要它的副本,它将返回非 const 类型值。我读到我们可以在函数参数既可以是 const 也可以是非常量的情况下使用完美转发(这样我们每次使用它时都将它们包装在 forward&lt;Type&gt; 中),但是如何将它用于返回的值呢?

另外,如果我只想不返回任何内容,我应该写return 0; 还是return NULL;?哪个更容易理解?

【问题讨论】:

  • 返回 std::forward(temp->value);这个呢?
  • @peco nullptr 是指针的NULL,我为什么要返回它?
  • 是的,你是对的
  • @peco 但我不知道如何处理函数声明 const Type&amp;&amp; operator[],我的意思是无论如何我必须向函数声明:const 和 non-const。
  • 您确定不需要只返回参考吗?完美转发主要适用于传递参数而不是返回。你也写你需要重复,这如何连接到完美的forawrding>

标签: c++ perfect-forwarding


【解决方案1】:

这种适用于所有人的统一语法,const/volatile/non-const/lvalue/rvalue/等,目前不支持隐式对象参数。但是,有一个提案P0847r4: Deducing this 添加了这个功能。有了这个,你可以说:

template <typename Self>
auto&& operator[](this Self&& self, int index)
{
    if (index >= self.size) { throw std::out_of_range("Error: excessive index"); }
    else if (index < 0) { throw std::out_of_range("Error: negative index"); }

    auto* temp = self.head;
    for (int i = 0; i < index; i++) { temp = temp->next; }        
    return std::forward_like<Self>(temp->value);
}

在它可用之前,您可以做的最好的事情是缩短const 和非const 重载的实现,并将这两个调用委托给一个静态帮助函数模板,实际上可以 em> 推导出隐式对象参数的 cv-qualification 和 value 类别:

class List
{
private:
    template <typename Self>
    static auto&& get(Self&& self, int index)
    {    
        if (index >= self.size) { throw std::out_of_range("Error: excessive index"); }
        else if (index < 0) { throw std::out_of_range("Error: negative index"); }

        Node* temp = self.head;
        for (int i = 0; i < index; i++) { temp = temp->next; }
        return temp->value;
    }

public:
    const Type& operator[](int index) const
    {
        return get(*this, index);
    }

    Type& operator[](int index)
    {
        return get(*this, index);
    }

private:
    // ...
};

DEMO

另外,请注意,返回引用的函数的惯用方法是在无法返回任何内容的情况下抛出异常,或者插入 ad-hoc 并返回一个新对象。

【讨论】:

  • 因为我一直在寻找一个干净简单的解决方案,我可能会选择重复项(因为我没有看到任何性能改进,并且重复项更容易理解),但这很有趣,谢谢!
  • 哇,新语法看起来很时髦。
猜你喜欢
  • 2018-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多