如果lvalue,请参考,如果rvalue进行复制,即使rvalue持久

Take a reference if lvalue and make a copy if rvalue i.e. make rvalue persistent

本文关键字:如果 rvalue 复制 即使 持久 参考 lvalue      更新时间:2023-10-16

我在移动和LVALUE语义上很新。我的印象是我做错了。这里实现FunctContainer后,我想编写的代码:

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的ctors,以便在fc1中存储的函数的寿命是f之一,并且包含功能的fc2中的寿命是fc2本身的寿命。

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

这是正确的C ,但错误的行为:f_f_是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 ,但旨在在伪代码中解释所需的行为是什么样的。如果可能

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

转发参考参考contapapsing 规则可以帮助您轻松实现此目标。

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)};
}
  • 当您使用 lvalue 调用makeFunctContainer时,T将是 lvalue参考。这意味着您将在FucntContainer中存储 lvalue参考

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


示例用法:

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

以来,由于C 17具有使用用户定义的扣除指南(类模板参数扣除)的类模板参数扣除。因此,您可以如下解决问题:

#include <utility>
#include <iostream>
template<typename FnT>
struct FunctContainer {
    constexpr FunctContainer(FnT f) : f_ { std::forward<FnT>(f) } {}
    FnT f_;
};
template<typename FnT>
FunctContainer(const FnT& f) -> FunctContainer<const FnT&>;
template<typename FnT>
FunctContainer(FnT&& f) -> FunctContainer<FnT>;
int
main(
) {
    auto f { [] { std::cout << "Hello, world!" << std::endl; } };
    FunctContainer f1 { f }; // stores reference to f in f1
    FunctContainer f2 { [] { std::cout << "Hello, world!" << std::endl; } }; // moves f into f2
    f1.f_();
    f2.f_();
    return 0;
}
相关文章: