有没有办法防止使用未检查的 std::optional?

huangapple go评论59阅读模式
英文:

Is there any way to guard against using an unchecked std::optional?

问题

出于我的目的,我需要能够确保我对可选项(optional)的.value的访问是有效的。在过去,我曾使用过一个宏来检查.has_value(),并调用return T来跳出执行,然后实例化一个对.value的本地引用,因为这意味着我从未直接调用过.value,而是在宏之后进行了检查工作。然而,我正在遵守的相同安全规则不允许我直接调用.value,同时也限制了我不使用宏,因为它们也被认为是不安全的。

在C++语言中是否有一种有条件地在堆栈上构造对象或返回的方法?

我考虑过使用.and_then(...),但在需要同时使用两个可选项(optional)的情况下,代码很快变得难以阅读(这是我必须满足的另一个安全度量标准)。

编辑:其他限制:

  • 我必须使用至少C++14。
  • 我不能使用异常。
  • 不能使用堆。
  • 不能“隐藏”对值或has_value的访问。
  • 移除可选项(optionals)的使用是可能的,但我正在寻找不移除它们的选项,因为改变一个大量使用可选项(optionals)的代码库以不使用它们是很多工作。根据迄今为止的评论和答案,看起来似乎没有保持我们的编码方式“类似于Rust”的方法。
  • XY问题的Y是:我们希望能够声称在可达的代码分支中没有终止。
  • X是这个,我们希望不必担心在.value调用中存在的终止,因为我们声称我们的代码在使用.has_value验证之前实际上从未调用它。
英文:

For my purposes, I need to be able to say that my access to the .value of an optional is guaranteed to be valid. In the past, I have used a macro that checked against the .has_value() and called return T to jump out of execution, and then instantiated a local reference to the return of .value, as that meant that I never directly called .value myself, and only after a macro did the checked work. However, the same safety rules I am working under which do not allow me to call .value directly, also limit me to not use macros as they are also deemed unsafe.

Is there any way to conditionally either construct an object on the stack or return in the C++ language?

I have considered using .and_then(...), but in the case of two optionals needed at once, the code swiftly becomes unreadable (which is another safety metric I must pass).

EDIT: other limitations:

  • I have to use C++14 at the latest.
  • I cannot use exceptions.
  • No heap usage.
  • No "hiding" the access to value or has_value.
  • Removing the usage of optionals is possible, but I am looking for options to not remove them as the effort involved in changing a codebase which uses them liberally to one which does not is a lot of work. As far as I can see from comments and answers so far, it looks like there is no way to keep the way we code "Rust-like".
  • The Y of the XY problem is: We want to be able to claim there are no terminates in any of the reachable code branches.
  • The X is this, we want to not have to worry about the terminate which does exist in the .value call by claiming our code never actually calls it without first verifying by using .has_value

答案1

得分: 1

不应直接使用value(或has_value)。对于单个可选项情况,请使用transformand_then,对于多个参数情况,请使用以下代码:

template <typename T>
struct is_optional : std::false_type{};

template <typename T>
struct is_optional<std::optional<T>> : std::true_type{};

template <typename T>
concept Optional = is_optional<std::remove_cvref_t<T>>::value;

template <typename F, Optional... Opts>
auto transform(F&& f, Opts&&... opts)
{
    return (opts && ...) ? std::optional{std::invoke(std::forward<F>(f), *std::forward<Opts>(opts)...)} : std::nullopt;
}

template <typename F, Optional... Opts>
auto and_then(F&& f, Opts&&... opts)
{
    return (opts && ...) ? std::invoke(std::forward<F>(f), *std::forward<Opts>(opts)...) : std::nullopt;
}
英文:

You shouldn't use value (or has_value) directly. Use transform and and_then for the single optional case, and the following for the multiple argument case.

template &lt;typename T&gt;
struct is_optional : std::false_type{};

template &lt;typename T&gt;
struct is_optional&lt;std::optional&lt;T&gt;&gt; : std::true_type{};

template &lt;typename T&gt;
concept Optional = is_optional&lt;std::remove_cvref_t&lt;T&gt;&gt;::value;

template &lt;typename F, Optional... Opts&gt;
auto transform(F&amp;&amp; f, Opts&amp;&amp;... opts)
{
    return (opts &amp;&amp; ...) ? std::optional{std::invoke(std::forward&lt;F&gt;(f), *std::forward&lt;Opts&gt;(opts)...)} : std::nullopt;
}

template &lt;typename F, Optional... Opts&gt;
auto and_then(F&amp;&amp; f, Opts&amp;&amp;... opts)
{
    return (opts &amp;&amp; ...) ? std::invoke(std::forward&lt;F&gt;(f), *std::forward&lt;Opts&gt;(opts)...) : std::nullopt;
}

huangapple
  • 本文由 发表于 2023年6月1日 17:28:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76380464.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定