什么是“常规类型"?在移动语义的上下文中?
Alex Stepanov 将常规类型定义为,这些类型满足有关复制和相等的某些属性.现在 C++11 已经将移动语义添加到泛型编程领域,Stepanov 的定义不再完整.我正在寻找有关常规类型的良好参考,其中包括它们与移动语义的交互.
Alex Stepanov defined Regular Types as types satisfying certain properties around copying and equality. Now that C++11 has added move semantics to the realm of generic programming, Stepanov's definition is no longer complete. I'm looking for a good reference on regular types that includes their interaction with move semantics.
推荐答案
总结:
对于 C++11,我会包括:
For C++11 I would include:
- move-ctor (
noexcept
) - 移动赋值(
noexcept
) - 总序(
operator<()
用于自然总序,std::less<>
总订单不存在). hash<>
- move-ctor (
noexcept
) - move-assign (
noexcept
) - total ordering (
operator<()
for natural total order andstd::less<>
if a natural total order does not exist). hash<>
并且会删除:
swap()
(非抛出) - 替换为移动操作.
swap()
(non-throwing) - replaced by move operations.
评论
Alex 在编程元素中重新审视了常规类型的概念.事实上,这本书的大部分内容都是针对常规类型的.
Alex revisits the concept of a regular type in Elements of Programming. In fact, much of the book is devoted to regular types.
有一组程序,其包含在计算中类型的基础让我们可以在数据结构中放置对象并使用将对象从一种数据结构复制到另一种数据结构的算法.我们称之为具有这种基础的类型是正规的,因为它们的使用保证行为的规律性和互操作性.-- EoP
There is a set of procedures whose inclusion in the computational basis of a type lets us place objects in data structures and use algorithms to copy objects from one data structure to another. We call types having such a basis regular, since their use guarantees regularity of behavior and, therefore, interoperability. -- Section 1.5 of EoP
在EoP中,Alex 引入了underlying_type 的概念,它为我们提供了一种可用于移动的非抛出交换算法.底层类型模板不能以任何特别有用的方式在 C++ 中实现,但您可以使用非抛出 (noexcept
) move-ctor 和 move-assign 作为合理的近似值(底层类型允许移动到/从一个临时的,而不对临时的进行额外的破坏).在 C++03 中,提供非抛出 swap()
是近似移动操作的推荐方法,如果您提供 move-ctor 和 move-assign 那么默认 std::swap()
就足够了(尽管您仍然可以实现一个更有效的方法).
In EoP, Alex introduces the notion of an underlying_type which gives us a non-throwing swap algorithm that can be used to move. An underlying_type template isn't implementable in C++ in any particularly useful manner, but you can use non-throwing (noexcept
) move-ctor and move-assign as reasonable approximations (an underlying type allows moving to/from a temporary without an additional destruction for the temporary). In C++03, providing a non-throwing swap()
was the recommended way to approximate a move operation, if you provide move-ctor and move-assign then the default std::swap()
will suffice (though you could still implement a more efficient one).
[我记录在案 建议您使用单个赋值运算符,按值传递,以涵盖移动分配和复制分配.不幸的是,当一个类型获得默认的 move-ctor 时,当前的语言规则导致这与复合类型中断.在语言中修复之前,您将需要编写两个赋值运算符.但是,您仍然可以对其他接收器参数使用按值传递,以避免在处理所有参数的移动/复制时出现组合.]
[ I'm on record as recommending that you use a single assignment operator, passing by value, to cover both move-assign and copy-assign. Unfortunately the current language rules for when a type gets a default move-ctor causes this to break with composite types. Until that is fixed in the language you will need to write two assignment operators. However, you can still use pass by value for other sink arguments to avoid combinatorics in handling move/copy for all arguments. ]
Alex 还添加了总排序的要求(尽管可能没有自然的总排序并且排序可能纯粹是代表性的).operator<()
应该保留用于自然全序.我的建议是专门化 std::less<>()
如果自然总排序不可用,标准中有一些先例).
Alex also adds the requirement of total ordering (though there may not be a natural total order and the ordering may be purely representational). operator<()
should be reserved for the natural total ordering. My suggestion is to specialize std::less<>()
if a natural total ordering is not available, there is some precedent for that in the standard).
在EoP 中,Alex 放宽了对平等的要求,以允许代表平等就足够了.一个有用的改进.
In EoP, Alex relaxes the requirements on equality to allow for representational-equality as being sufficient. A useful refinement.
常规类型也应该是等式完整的(即,operator==()
应该可以实现为非友元、非成员函数).等式完备的类型也是可序列化的(尽管没有规范的序列化格式,实现流操作符除了调试之外几乎没有用处).等式完备的类型也可以散列.在 C++11(或使用 TR1)中,您应该提供 std::hash
的特化.
A regular type should also be equationally complete (that is, operator==()
should be implementable as a non-friend, non-member, function). A type that is equationally complete is also serializable (though without a canonical serialization format, implementing the stream operators are of little use except for debugging). A type that is equationally complete can also be hashed. In C++11 (or with TR1) you should provide a specialization of std::hash
.
常规类型的另一个属性是 area()
还没有任何标准语法 - 除了测试之外,可能几乎没有理由实际实现.这是用于指定复杂性的有用概念 - 我经常实现它(或近似值)以测试复杂性.例如,我们将复制的复杂度定义为以复制对象区域的时间为界.
Another property of regular types is area()
for which there is not yet any standard syntax - and likely little reason to actually implement except for testing. It is a useful concept for specifying complexity - and I frequently implement it (or an approximation) for testing complexity. For example, we define the complexity of copy as bounded by the time to copy the area of the object.
常规类型的概念不是特定于语言的.当我接触到一种新语言时,我做的第一件事就是弄清楚常规类型在该语言中的表现方式.
The concept of a regular type is not language-specific. One of the first things I do when presented with a new language is work out how regular types manifest in that language.
相关文章