微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

提供可选参数的现代C ++方法

如何解决提供可选参数的现代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 举报,一经查实,本站将立刻删除。