【问题标题】:Equivalent of const_cast for std::optional等价于 std::optional 的 const_cast
【发布时间】:2013-09-23 21:03:06
【问题描述】:

我的类的接口包括一个可能不存在的对象的访问器。目前,它返回一个可能为空的指针。我想按照建议的herestd::optional 替换指针。访问器有一个const 重载,它使用Meyers' const_cast trick 来避免重复相同的代码两次。

简而言之,我想替换这个:

T const * MyClass::get() const { 
    /* non-trivial */ 
}
T * MyClass::get() { 
    return const_cast<T *>(const_cast<MyClass const *>(this)->get()); 
}

用这个:

std::optional<T const &> MyClass::get() const { 
    /* non-trivial */ 
}
std::optional<T &> MyClass::get() {
    auto t = const_cast<MyClass const *>(this)->get();
    return t ? std::optional<T &>(const_cast<T &>(* t)) : std::nullopt;
}

替换似乎不令人满意,因为:

  1. 它引入了一个分支;
  2. 额外的复杂性在某种程度上违背了使重载成为轻量级的目标(并被编译器简单地优化掉)。

我假设引用的 std::optional 特化基本上可以归结为一个增加安全性的指针,因此想知道是否有某种方法可以保持指针解决方案的简单性。有没有更令人满意的方法来编写访问器重载以使用std::optional

【问题讨论】:

  • 您确定可以直接使用std::optional 的引用吗?阅读 n3690,我觉得它需要一个对象类型,例如指针或std::reference_wrapper
  • 现在还有支持std::optional的编译器吗?
  • 你不能在引用上实例化 std::optional (提出提案的人认为这太有争议了,可能会阻止 optional 被添加到 C++1y 中)。从 n3690 (C++1y CD) 20.6.2p1 开始:“需要为引用类型或(可能是 cv 限定的)类型 in_place_t 或 nullopt_t 实例化模板可选的程序是格式错误的。”
  • optional 位于树干末端 libc++ 中,可使用带有 -std=c++1y 的树干末端 clang 进行访问。它 static_asserts 用于引用类型。
  • optional 刚刚从 C++14 中被选为 TS。它可能很快会移至 libc++ 中的&lt;experimental/optional&gt;

标签: c++ pointers constants optional c++14


【解决方案1】:

正如其他人所提到的,在 c++14 标准中使用引用类型实例化 std::optional 是错误的。 (参见N3690 20.6.2。)因此,除非您愿意,否则使用std::optional 作为指针(指向其缺失由值nullptr 表示的单个对象)的替代是不可行的按值复制对象,而不是按引用。

但是,该规范为将来添加此类功能敞开了大门。此外,section 7.15N3672 建议使用 std::reference_wrapper 的解决方法。

更新:此外,@HowardHinnant 告诉我,标准中的内容已完全从 c++14 中剔除。

【讨论】:

    猜你喜欢
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 2020-11-17
    相关资源
    最近更新 更多