传递可选对象而无需复制它

Pass optional object without copying it

本文关键字:复制 对象      更新时间:2023-10-16

我在重构旧代码时遇到以下情况:

// pointers to const are discouraged in our code base
void Do(Foo* exists, Foo* maybe_null) {
  // does not change *exists or *maybe_null
}
int main() {
  // ...
  Do(&foos[i], test_both ? &bars[i] : nullptr);
  // ...
  HighOrderFunction(foos, bars, &Do);
  // ...
}

因此,Do带有两个Foo对象,其中一个肯定存在,而第二个对象可能不存在,具体取决于某些外部测试。我试图解决的当前代码有问题:

  • 第一个参数永远不会为null,因此永远不会使用其指针属性。

  • 我通常不喜欢将空用作空值的使用。

到目前为止,我提出了三种可能的解决方案,我都不对此感到完全满意:

  • Do(const Foo&, Foo*):第二个参数与以前相同,现在呼叫语法不再统一(foos[i]&bars[i]),这可能会使读者感到困惑。

  • Do(const Foo&, const optional<Foo>&):必须复制第二个Foo对象才能构造可选的。

  • Do(const Foo&, optional<const Foo&>):由于不允许参考类型的可选类型,因此实际上无法工作。

  • Do(const Foo&)Do(const Foo&, const Foo&)超载:当我需要通过功能指针

  • 将DO通过时会引起问题

那么,在这种情况下,我可以使用更好/清洁的解决方案吗?

(我使用的是C 11,以及一些诸如可选的类别添加)

使Do成为函数,而不仅仅是函数。

 struct Do
 {
      void operator()(const Foo &must_be_provided);
      void operator()(const Foo &must_be_provided, const Foo &maybe_unneeded);
 };

,然后在实施两种形式的Do::operator()之后,

 void some_function(Do f)
 {
       // assume access to foos and bars here
     if (test_both)   // assume determined at run time
         f(foos[i]);
     else
        f(foos[i], bars[i]);
 }

请注意,函数可以按值,参考或其地址传递,或者可以以指针传递(尽管调用函数的语法都会有些变化)。

如果您需要可选参考,则可以使用std::reference_wrapper<Foo>

Do(const Foo&, optional<std::reference_wrapper<const Foo>>)

将避免复制对象。并将使该函数正式接受参考。

确保创建了一个reference_wrapper对象。但这很轻。大多数实现只会掩盖指针。