传递可选对象而不复制它
Pass optional object without copying it
我在重构旧代码时遇到了以下情况:
// 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 用作空值。
到目前为止,我想出了三个可能的解决方案,none 其中我完全满意:
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 作为函数指针传递时会导致问题
那么,有什么 better/cleaner 我可以在这种情况下使用的解决方案吗?
(我正在使用 C++11 和一些 std 添加,例如可选)
使 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
对象。但它相当轻。大多数实现只是屏蔽一个指针。
我在重构旧代码时遇到了以下情况:
// 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 用作空值。
到目前为止,我想出了三个可能的解决方案,none 其中我完全满意:
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 作为函数指针传递时会导致问题
那么,有什么 better/cleaner 我可以在这种情况下使用的解决方案吗?
(我正在使用 C++11 和一些 std 添加,例如可选)
使 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
对象。但它相当轻。大多数实现只是屏蔽一个指针。