【发布时间】:2014-10-29 04:09:45
【问题描述】:
最近我看到很多关于泛型编程的资料,但在设计类型时,我仍然无法理解一件事。我不确定什么是最好的方法,让我解释一下。
对于某些类型,提供默认构造函数是很自然的。 该类型的所有可能构造都是有效的,或者默认值是有意义的,因此提供默认值是有意义的。这是基本类型的情况。
后来,有些类型默认构造它们不会产生值。例如,在标准库中,我们有 std::function<Sig> 和 std::thread。然而,它们是默认可构造的,即使它们没有持有值。
后来,我们在标准中提出了optional<T>。将它用于基本类型很有意义,因为对于基本类型,所有可能的赋值都表示一个有效值(double 和 float NaN 除外),但我不知道您将如何将它用于 thread 或std::function<Sig>,因为这些类型在构造时不包含“值”。就像这些类型直接嵌入在类型中的“可选”一样。
这有这些缺点。由于没有“自然”的默认(或值)构造,例如 int:
- 现在我必须在我的所有设计中用
if (valid)乱扔我的班级并发出错误信号。或 - 如果我不进行此检查,则使用起来会不太安全。前提条件 -> 如果默认构造,则在使用前分配。
所以当我想设计一个类型时,我总是会发现一个问题:我应该让它默认可构造吗?
优点:
- 更容易在更通用的上下文中重用,因为如果我添加适当的操作,我的类型将更容易建模 SemiRegular 或 Regular。
缺点:
- 用
if声明在整个班级中乱扔垃圾,或者与用户签订合同,其中班级使用起来更不安全。
例如,假设我有一个带有 ID、艺术家、标题、持续时间和年份的课程 Song。标准库使类型默认可构造是非常好的。但是:
- 我无法找到一种自然的方式来构建“默认歌曲”。
- 我不得不乱扔
if (validsong),否则使用起来不安全。
所以我的问题是:
我应该如何设计一个没有“自然(如值)”默认值的类型?我是否应该提供默认构造函数?
在我选择提供默认构造函数的情况下,
optional<T>如何适应所有这些难题?我的观点是,让一个不是“自然”默认可构造的类型提供默认构造函数会使optional<T>在这种情况下毫无用处。-
optional<T>是否应该只用于值域完整的类型,也就是说,我不能为其表示分配无效值,因为它们都包含一个值,例如 int? 为什么在标准中首先将
std::function<Sig>等类型设为默认可构造?构造时,它不保存值,所以我不明白为什么应该提供默认构造函数。你总是可以这样做:optional<function<void ()>>,例如。这只是一个设计选择,两者都是有效的,还是有一个设计,在这种情况下,关于选择默认与非默认可构造优于另一个?
【问题讨论】:
-
实际上,我对 Stepanov 和 Sean Parent 对这些问题的看法非常感兴趣。有什么材料吗? P.S.:编程要素没看完,可能有回复。
标签: c++ optional default-constructor