【问题标题】:C++ 11x check: how to implement const-variants? [duplicate]C++ 11x 检查:如何实现 const-variants? [复制]
【发布时间】:2012-10-11 22:12:45
【问题描述】:

在 C++ 11 之前,我经常需要实现一个方法的两个非常相似的变体来处理类/结构的 const 和 non-const 使用场景:

struct my_struct_t{
     ....
     float_t& at( uint32_t row, uint32_t col)
     {
         return *(((float_t*)((uint8_t*)numbers+row*row_stride)) + col);
     }

     float_t const& at( uint32_t row, uint32_t col) const
     {
         return *(((float_t*)((uint8_t*)numbers+row*row_stride)) + col);
     }

};

这在 C++ 11 中是否发生了变化?

【问题讨论】:

  • 如果两个变体的作用完全相同,那么您可以保留const 变体并摆脱另一个变体。
  • 我不相信你的第一个会起作用。返回对非 const 临时值的引用。
  • @Mike 是的,回报有缺陷,我现在正在修复它们。

标签: c++ c++11


【解决方案1】:


这在标准库中很明显(它仍然使用显式的const 方法)。

【讨论】:

  • 我没有检查 STL 的实现,因为,有几个 STL 实现。而且它们中的大多数都经过调整以支持 C++ 11 之前的编译器,因此,它们不一定提供明确的答案。
  • @dsign 但是 Mark 是对的,因为 C++11 标准确实为标准库定义了接口,并且仍然提供了某些 getter 类型函数的 const/non-const 版本,例如en.cppreference.com/w/cpp/container/vector/operator_at
  • @dsign 是的。他们有几个实现。但是每个正确的实现都必须满足约束和行为要求。现在这并没有留下太大的差异空间。
  • 这样就解决了。我只是想快速检查一下我是否遗漏了什么,我明白了!谢谢大家。
【解决方案2】:

我认为没有必要摆脱“不实现 2 个变体”。

  1. 如果两个变体做不同的事情,那么您必须 保留它们
  2. 如果两个变体执行相同的操作,则删除 非常量版本并仅维护const 版本

顺便说一句,如果需要的话,还有第 3 和第 4 种变体:

float_t& at( uint32_t row, uint32_t col) volatile;
float_t& at( uint32_t row, uint32_t col) const volatile;

[注意:不相关,但在 C++11 中,所有变体都可以使用 noexcept 关键字添加异常相关信息:

float_t& at( uint32_t row, uint32_t col) noexcept;

]

【讨论】:

  • 重点是两个版本相同,但它们返回不同的东西,通常是常量引用与非常量引用,要么是*this要么给内部成员。一个典型的例子是容器的operator[]en.cppreference.com/w/cpp/container/vector/operator_at
  • @jogojapan,如果方法返回不同的东西,那么它们就不会做同样的事情:)。返回非常量引用可以在外部修改,但 const 引用不能。
  • @jogojapan 说清楚了。也许我遗漏了一些东西,但没有非常量版本分配将无法工作:'distances->at(i, j) = d;'
  • @iammilind 是的。但我理解这个问题的方式是关于一个函数的两个版本的实例,它们返回不同的东西但执行相同的操作,以及如何避免代码重复。在我看来,主要的答案(即使在 C++98 中)是所有重要的操作都应该在一个单独的(可能是私有的、非常量的)函数中执行,并且这两个版本应该只为一个 getter 实现,或者同样微不足道的事情。
  • (解释我的反对意见。)dsign 和 jogojapan 是对的:在其他方面相同的访问器具有 const 和 non-const 风格是 C++ 中非常常见的反模式。文字游戏可能会掩盖问题,但不会让它消失。
【解决方案3】:

这在 C++11 中没有改变,但在 C++17 中有所改变:

T const & f() const {
    return something_complicated();
}
T & f() {
    return const_cast<T &>(std::add_const(*this).f());
}

How do I remove code duplication between similar const and non-const member functions?

编辑

自从发表这篇文章以来,我已经改变了几次立场。上面的文字反映了我目前的想法。我之前的位置是两个演员都更喜欢const_cast,我原来的位置是static_cast,然后是const_castconst_cast 更安全,因为它唯一能做的就是添加/删除 constvolatile 限定符。 static_cast 可能会以其他方式意外投射。我最初的想法是更喜欢static_cast 添加const,因为它将添加const 的最可能“安全”操作与删除const 的可能危险操作分开。上面代码中的版本具有std::as_const 规定的安全操作,它只能执行我想要的操作,而将潜在不安全的const_cast 作为您唯一需要确保您正确执行的操作。

【讨论】:

  • 你的意思是self.f()
猜你喜欢
  • 1970-01-01
  • 2021-03-27
  • 2012-05-29
  • 2010-12-21
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多