现代 C++ 中的目标类型

Bli*_*ndy 2 c++

当我说目标类型时,我的意思是使用接收器变量或参数的类型作为信息来推断我分配给它的部分代码。例如,在 C# 中,您可以编写类似的代码来传递可为 null 的值或null(空)(如果需要):

void f(int? i) {}
void caller(bool b) => 
    f(b ? 5 : null);  // value is bound to an int? parameter so all information 
                      // to build this object is already in code
Run Code Online (Sandbox Code Playgroud)

我能想到的最好的 C++ 是这样的:

void f(const optional<int>& i) {}
void caller(bool b)
{
    f(b ? make_optional(5) : optional<int>());
}
Run Code Online (Sandbox Code Playgroud)

它有效,但它要求我编写optional两次并提供一次可选类型,即使所有信息都应该已经在代码中。以我的拙见,这就是类型推断应该为您做的事情,而不必每行重复多次。因为以下确实有效:

optional<int> i;
i = {};  // empty
i = {5}; // a value
Run Code Online (Sandbox Code Playgroud)

我本以为下一个合乎逻辑的步骤也会起作用:

void f(const optional<int>& i) {}
void caller(bool b)
{
    f(b ? {5} : {});  // doesn't compile
}
Run Code Online (Sandbox Code Playgroud)

因此,总体而言,从各种实验来看,目标键入似乎在直接将值分配给变量时有效,但不能作为绑定到参数的三元条件表达式的一部分?我的理解正确吗?C++ 版本没有限制,例如我一直在 MS C++20 中编写此内容。

还有一个相关的问题,虽然不是我问题的主要焦点,但是否有更好的方法来编写optional<>可以具有值或不基于布尔值的初始化?

Yak*_*ont 9

在 C++ 中,表达式具有类型。

{}然而,这不是一个表达式。{}当您期望表达式应该出现时,可以使用一些受限上下文。这不会变成{}一个表达式。

?:是一个操作,它的参数必须有类型。的类型?:源自其 2 个参数的类型(规则很复杂,但它试图找到一个共同的类型)。

b ? std::optional{5} : std::nullopt;
Run Code Online (Sandbox Code Playgroud)

与你想要的类似。std::nullopt这里,可以转换为 a 的事实std::optional<int>用于推导?:表达式的类型。

你也可以写:

template<class T>
std::optional<std::decay_t<T>> maybe( bool b, T&& t ) {
  if (!b) return std::nullopt;
  return std::forward<T>(t);
}
Run Code Online (Sandbox Code Playgroud)

这可以让你写

maybe( b, 5 )
Run Code Online (Sandbox Code Playgroud)

对于你的情况。

可以做更奇特的事情,您可以使用template<class T> operator T()类型来推断您要返回的类型。

但是,一般来说,C++ 类型系统是单向的。

  • @Blindy你不需要写任何东西。`nullopt` 是标准的,而“非泛型”的 `Optional` 只是使用 C++17 类模板推导规则 (2认同)