以下概念来自《C++20 - 完整指南》(改编自http://wg21.link/p0870),禁止缩小转换范围。例如,float
to int
,如1.9f
→中所示1
。
template <typename From, typename To>
concept ConvertibleWithoutNarrowing = requires (From&& from) {
{ std::type_identity_t<To[]>{std::forward<From>(from)}} -> std::same_as<To[1]>;
};
本书将其用于集合 C,在添加数据时不得进行缩小转换:
template<typename C, typename T>
requires ConvertsWithoutNarrowing<T, typename C::value_type>
void add(C& collection, const T& val) {…}
// Usage:
std::vector<int> vec_i;
add(vec_i, 1); // OK
add(vec_i, 1.3); // Does not compile.
我了解这个概念背后的总体思路,但[1]
最后一部分的std::same_as<To[1]>;
作用是什么?
TL;DR
[1]
明确指定用于比较的大小array
必须是1
。使用数组可以节省大量工作。进一步解释:
1. 但为什么
array
首先要使用?C++ 对数组类型缩小的限制
创建数组时,C++ 要求用于初始化数组的元素类型不得涉及任何收缩转换
因此如果你尝试编译
您将收到类似这样的错误
narrowing conversion from double to int
。初始化失败,因为您无法在不明确截断或转换值的情况下直接将 double 分配给 int 数组。2. 关于“简短的技巧要求”
提供的概念
确保可以将类型的值
From
转换为类型To
而不会丢失信息(即不允许进行缩小转换)。诀窍在于利用数组初始化和缩小转换的更严格规则,以避免需要明确编写这些情况的检查(例如,整数到浮点数、浮点到整数)。如果没有它,你需要更多的参与才能实现类似的结果:这个概念将会爆发为:
而且这仅涵盖算术类型的情况!对于不依赖数组初始化约束的真正等效实现,您需要再次手动添加每个可能的缩小情况。
3. 思考概念的另一种方式:它们会问关于类型的问题
理解 using 的一个简单方法
ConvertibleWithoutNarrowing
是将其视为“询问”以下问题:From
如果可以转换为To
不缩小的范围,则答案是“是” 。为了进行比较,检查允许缩小的转换的概念的可能实现是:
你可以把这个概念看作是“询问”:
From = double
现在考虑和的情况的这些“问题”To = int
:ConvertibleWithoutNarrowing
失败,因为类型无法在初始化列表中double
缩小到;但是int
ConvertibleWithNarrowing
通过,因为允许缩小double
到int
列表初始化之外- 它只是将其截断为整数。