传递可选对象而不复制它

时间:2017-01-01 13:06:29

标签: c++ c++11 pointers optional

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

// 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,因此永远不会使用其指针属性。

  • 我通常不喜欢使用null作为空值。

到目前为止,我提出了三种可能的解决方案,其中没有一种我完全满意:

  • Do(const Foo&, Foo*):第二个参数与之前的问题相同,现在调用语法不再统一(foos[i]&bars[i]),这可能会使读者感到困惑。< / p>

  • Do(const Foo&, const optional<Foo>&):必须复制第二个Foo对象以构建可选项。

  • Do(const Foo&, optional<const Foo&>):实际上不起作用,因为不允许引用类型的可选项。

  • Do(const Foo&)Do(const Foo&, const Foo&)重载:当我需要将Do作为函数指针传递时导致问题

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

(我正在使用C ++ 11和一些像可选的标准添加)

2 个答案:

答案 0 :(得分:2)

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

请注意,可以通过引用传递值,或者可以通过指针传递其地址(尽管调用函数的语法稍有变化)。

答案 1 :(得分:2)

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

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

这样可以避免复制对象。并且会使函数正式接受引用。

确定已创建reference_wrapper个对象。但它相当轻松。大多数实现只是屏蔽指针。