如果是左值,请参考;如果是右值,请进行复制,即使右值保持不变 [英] Take a reference if lvalue and make a copy if rvalue i.e. make rvalue persistent

查看:121
本文介绍了如果是左值,请参考;如果是右值,请进行复制,即使右值保持不变的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在move和lvalue语义上还很新。我有一种错的印象。在这里
一旦实现 FunctContainer 我想要编写的代码:

I'm pretty new in move and lvalue semantics. And I have the impression I'm doing it wrong. Here the code I want to be able to write once FunctContainer is implemented:

std::function<double(double)> f = [](double x){return (x * x - 1); };

FunctContainer fc1 = FunctContainer(f);

FunctContainer fc2 = FunctContainer([](double x){return (x * x - 1); });

我想写 FunctContainer 的代码因此,存储在 fc1 中的函数的生存期是 f 之一,而生存期在 fc2 包含的功能是 fc2 本身的生存期。

I want to write FunctContainer's ctors so that the lifetime of the function stored in fc1 is the one of f and the lifetime in fc2 of the contained function is the lifetime of fc2 itself.

我写了一些东西(见下文),但我不太满意(我弄错了)。

I have written something (see below) but I'm not really satisfied (I got it wrong).

这是正确的c ++,但行为错误:当 f _ 是一个右值时, f _ 在调用构造函数后到期。

This is correct c++ but wrong behavior: f_ expires after the call to the constructor when f_ is an rvalue.

class FunctContainerWRONG{
public:
  IntegrandNotProjecting(const std::function<double(double)>& function)
    : f_(function){}
  IntegrandNotProjecting(const std::function<double(double)>&& function)
    : f_(std::move(function)){}
  const std::function<double(double)>& f_;
private:
};

这对我来说似乎很糟糕,可能不是正确的c ++,但旨在用伪代码解释所需的内容行为看起来像。如果可能,我想避免构造一个全新的对象,而只想让我的对象持久:

This looks awful at me and probably is not correct c++ but is intended to explain in pseudocode what the desired behavior looks like. If possible I want to avoid to constuct a brand new object and I just want to let my object "persist":

class FunctContainer{
public:
  FunctContainer(const std::function<double(double)>& function)
    : f_p(nullptr), 
      f_(function){}
  FunctContainer(const std::function<double(double)>&& function)
    : f_p()std::make_shared<std::function<double(double)>>(function)), 
      f_(*f_p){}
private:
    std::shared_ptr<std::function<double(double)>> f_p;
    const std::function<double(double)>& f_;
};


推荐答案

转发参考引用折叠规则可以帮助您轻松实现这一目标。

Forwarding references and reference collapsing rules can help you achieve this easily.

template <typename T>
struct FunctContainer 
{
    T _f;

    template <typename TFwd>
    FunctContainer(TFwd&& f) : _f{std::forward<TFwd>(f)} { }
};

template <typename T>
auto makeFunctContainer(T&& f) -> FunctContainer<T>
{
    return {std::forward<T>(f)};
}




  • 调用<$ c带有左值 T 的$ c> makeFunctContainer 将是左值引用。这意味着您将在 FucntContainer 内存储左值引用

    • When you invoke makeFunctContainer with an lvalue, T will be an lvalue reference. This means that you'll store an lvalue reference inside FucntContainer.

      当您使用 rvalue 调用 makeFunctContainer 时, T 将是一个。这意味着您将在 FucntContainer 中存储一个 value

      When you invoke makeFunctContainer with an rvalue, T will be a value. This means that you'll store a value inside FucntContainer.

      示例用法:

      auto fc0 = makeFunctContainer(std::move(f0)); // `fc0` owns `f0`
      auto fc1 = makeFunctContainer(f1); // `fc1` stores a reference to `f1`
      

      这篇关于如果是左值,请参考;如果是右值,请进行复制,即使右值保持不变的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆