如何解决提供可选参数的现代C ++方法
让我们接受以下函数声明:
void print(SomeType const* i);
在这里,参数const*
的{{1}}性质表明了该参数是 optional 的意图,因为它可能是i
。如果不希望这样做,则该参数将只是一个nullptr
。交流 optional 语义当然不是设计指针的初衷,但是使用它们进行通信恰好可以长期工作。
现在,由于在现代C ++中通常不鼓励使用原始指针(应避免使用const&
和std::unique_ptr
来精确地表示特定的所有权-语义),我想知道如何正确地指示函数参数的可选-语义而不通过值传递,即。 e。 复制,为
std::shared_ptr
会的。
考虑了一段时间后,我想到了使用的想法:
void print(std::optional<SomeType> i);
这实际上是最精确的。但是事实证明,void print(std::optional<SomeType const&> i);
cannot have reference types。¹
还使用
std::optional
绝不是最佳选择,因为从那时起,我们将要求我们的void print(std::optional<SomeType> const& i);
存在于呼叫方侧的SomeType
中,再次可能(或者更可能是 )需要副本那里。
问题:那么允许可选参数不进行复制的一种很好的现代方法是什么?在现代C ++中使用原始指针还是一种合理的方法吗?
¹:具有讽刺意味的是,std::optional
不能具有引用类型(关于重新绑定或分配时转发的争议)的描述原因不适用于 const 的std::optional
s情况>参考,因为它们无法分配给它们。
解决方法
接受原始指针非常好,并且仍然可以在许多“现代”代码库中完成(我会注意到这是一个快速发展的目标)。只需对函数发表评论,说它可以为空,并且函数在调用后是否持有指针的副本(即,指向值的生存期要求是什么)。
,函数重载在这里提供干净的解决方案吗?例如。要声明该函数的const ref和空参数列表版本吗?
这可能取决于函数主体在无参数/空情况下的工作方式,以及如何管理这两种实现以最大程度地减少代码重叠。
原始指针通常适合这种类型的可选参数传递,实际上,这是唯一整体上使用原始指针的唯一一次。这也是规范的推荐方法。
话虽这么说,boost::optional
确实允许您使用引用可选和const引用可选。决定在std
库中使用此功能(出于我在此省略的原因)。
在这里,参数
const*
的{{1}}性质暗示了这一意图,该参数是可选的,因为它可能为nullptr。[...]
那么允许不复制而使用可选参数的现代方法又是什么呢?
根据可选参数是否存在,允许一个可选参数(不是i
的意思,而是语义上的)的实现变化,这听起来像是重载的理想候选者:
std::optional
或
struct SomeType { int value; };
namespace detail {
void my_print_impl(const SomeType& i) {
std::cout << i.value;
}
} // namespace detail
void my_print() {
const SomeType default_i{42};
detail::my_print_impl(default_i);
}
void my_print(const SomeType& i) {
detail::my_print_impl(i);
}
或类似的变体,具体取决于您的实现应根据可选参数的存在/不存在执行什么操作。
否则,可选引用基本上是原始指针,也可以使用后者(如果不适用重载)。
,这实际上是std :: reference_wrapper的用途。另请参见Does it make sense to combine optional with reference_wrapper?,以获取有关何时使用和何时不使用它的更多理由。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。