当我说目标类型时,我指的是使用接收者变量或参数的类型作为信息来推断我分配给它的代码的部分。例如,在C#中,您可以编写类似这样的东西,以便在必要时传递一个可空值或一个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我在C++中所能想到的最好的方法是:
void f(const optional<int>& i) {}
void caller(bool b)
{
f(b ? make_optional(5) : optional<int>());
}它可以工作,但它要求我编写两次optional并提供一次可选类型,尽管所有信息都应该已经在代码中了。这就是,在我看来,类型推断应该为你做什么,而不必重复自己的每一行多次。而且由于以下几点是可行的:
optional<int> i;
i = {}; // empty
i = {5}; // a value我原以为下一个合乎逻辑的步骤也会奏效:
void f(const optional<int>& i) {}
void caller(bool b)
{
f(b ? {5} : {}); // doesn't compile
}因此,从各种实验来看,目标类型似乎在将值直接赋值给变量时起作用,而不是作为绑定到参数的三元条件表达式的一部分?我理解得对吗?C++版本没有限制,例如,我一直在用MS C++20编写这篇文章。
还有一个相关的问题,虽然不是我问题的重点,但是是否有更好的方法来编写基于布尔值的optional<>初始化呢?
发布于 2022-01-18 19:58:18
在C++中,表达式有类型。
然而,{}不是一个表达式。有一些受限的上下文,当您期望表达式应该放在那里时,可以在其中使用{}。这并不能使{}变成表达式。
?:是一个操作,它的参数必须有类型。?:的类型是从它的2个参数的类型派生出来的(规则很复杂,但它试图找到一个公共类型)。
b ? std::optional{5} : std::nullopt;和你想要的一样。在这里,std::nullopt可以转换为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);
}这让你可以写
maybe( b, 5 )为你的案子。
可以做更好的事情,您可以在类型上使用template<class T> operator T()来推断您要返回的类型。
但是,一般来说,C++类型的系统是单向的。
发布于 2022-01-18 20:02:21
@Yakk-AdamNevraumont已经给出了完整的答案,所以我只给出一个简短的答案,如果您切换短版本的三元操作符条件,您的代码可以工作,并使用完整的if语句:
void f(const optional<int>& i) {}
void caller(bool b)
{
if (b) {
f(5);
}
else {
f({});
}
}https://stackoverflow.com/questions/70761598
复制相似问题