提问人:einpoklum 提问时间:8/13/2022 更新时间:8/13/2022 访问量:150
C++ 是否具有 SQL 合并的等价物?
Does C++ have some equivalent of SQL coalesce?
问:
在 SQL 中,是一个可变参数函数,它返回其第一个非 null 参数,否则返回 null。COALESCE(val_1, val_2, ... val_n)
现在,在 C++ 中,我们有指针,这些指针可以是 null,但也有自 C++17 以来的指针,并且有可以为 null 或保存单状态类型的指针。std::optional
std::variant
C++ 中是否有一些标准库函数接受多个可为 null(或可清空)对象并返回第一个非 null?如果没有,是否提出了一个,例如在一元编程的背景下?
答:
3赞
lorro
8/13/2022
#1
不知道任何,但你可以很容易地写一个:
template<typename T>
auto coalesce(T&& t) { return *t; }
template<typename T1, typename... Ts>
auto coalesce(T1&& t1, Ts&&... ts)
{
if (t1)
{
return *t1;
}
return coalesce(std::forward<Ts>(ts)...);
}
您还可以将其设置为运算符(例如,在命名空间中,这样您就不会污染全局运算符)或将其设置为自定义运算符。
以上解决了传递可为 null 类型的问题。根据要求,这里有一个版本,适用于你想混合可为 null 和不可为 null 的情况 - 对于不可为 null 的,它当然会返回第一个不可为 null。这使用 C++20:
template<typename T1, typename... Ts>
auto coalesce(T1&& t1, Ts&&... ts)
{
if constexpr (requires { *t1; })
{
if constexpr (sizeof...(ts))
{
return coalesce(std::forward<Ts>(ts)...);
}
return *t1;
}
return std::forward<T1>(t1);
}
请注意,即使此版本也存在一个问题,即您只能使用一种基础类型(如 must exist)调用它。如果您希望能够处理多个(可能)不相关的基础类型,则可以求助于延续传递:std::common_type<T1, Ts...>
template<typename Cont, typename T1, typename... Ts>
auto coalesce(const cont& c, T1&& t1, Ts&&... ts)
{
if constexpr (requires { *t1; })
{
if constexpr (sizeof...(ts))
{
return coalesce(cont, std::forward<Ts>(ts)...);
}
return cont(*t1);
}
return cont(std::forward<T1>(t1));
}
评论
0赞
einpoklum
8/13/2022
这并不能区分空虚/空虚和虚假......弱类型语言中一个非常常见的错误:-P
0赞
lorro
8/13/2022
@einpoklum 在 C++ 中,对于 OP 询问的类型,首先检查空值,然后使用取消引用 op,然后检查值(即 falseness)。所以这里没问题。当然,您可能会断言,例如 在 / 上可用,但我看不出有理由用它来转移注意力。operator*
t
t1
0赞
einpoklum
8/13/2022
你的代码不会这样做,它只是检查错误。
0赞
lorro
8/13/2022
@einpoklum所以。我希望它只在可为 null 的类型上调用。由于调用方知道类型,因此我只看到这些类型这样做的原因。如果要包含对不可为 null 类型的支持,可以简单地通过检查是否存在 () 来启动第二个函数,如果不可用,则返回转发。这回答了你的问题吗?t1::operator*()
is_detected
t1
operator*()
1赞
lorro
8/13/2022
@NathanPierson 这里的类型必须相同或具有共同的类型(如 ,即不要期望它与 和 一起使用)。因此,我首先不理解 einpoklum 的请求:您可能只使用相同类型的 nullable 来调用它。但是,通过 cps,您可以拥有非常不同的类型。还添加了一个示例。std::common_type<>
int*
float*
评论
?:
a ?: b
a
b
a ? a : b
a