将常数或非常数引用存储在同一类模板中

问题描述 投票:1回答:1

下面的示例是简陋的,因为我想了解这个概念。

假设我们想要一个数组的1元素view

我的问题是如何使它同时与constnon-const对象一起使用。

我知道为什么下面的代码中的第二个块不能编译,但是我不知道如何组织代码以同时满足两种情况。

#include <cassert>
#include <array>

template <typename T>
class View {
 private:
  const std::size_t index_;
  T &t_;
  using value_type = typename T::value_type;

 public:
  View(T &t, std::size_t index) : t_{t}, index_{index} {}

  const value_type &value() const { return t_[index_]; }
  value_type &value() { return t_[index_]; }
};

int main() {
  using Array = std::array<int, 2>;

  // The block below works
  {
    Array array{0, 0};
    View<Array> view(array, 0);
    view.value() = 5;
    assert(array[0] == 5);
  }

  // The block below gives a compilation error
  {
    const Array array{5, 5};
    View<Array> view(array, 0);
    assert(view.value() == 5);
  }
}
c++ const
1个回答
3
投票

以下作品:

#include <cassert>
#include <array>

template <typename T>
class View {
 private:
  using value_type = typename T::value_type;

  T &t_;
  const std::size_t index_;

 public:
  View(T &t, std::size_t index) : t_{t}, index_{index} {}

  const value_type &value() const { return t_[index_]; }

  template<class Arr = T, class = typename std::enable_if<!std::is_const<Arr>::value>::type>
  value_type &value() { return t_[index_]; }
};

int main() {
  using Array = std::array<int, 2>;

  // The block below works
  {
    Array array{0, 0};
    View<Array> view(array, 0);
    view.value() = 5;
    assert(array[0] == 5);
  }

  // The block below gives a compilation error
  {
    const Array array{5, 5};
    View<const Array> view(array, 0);
    assert(view.value() == 5);
  }
}

如果给View赋予const Array,还必须指定const Array作为模板参数。

但是如果数组类型为const,返回带有value()的非const引用将不再起作用,因此我们将使用SFINAE禁用此功能。

PS:如果名为View的类确实是某个视图下所期望的,即没有修改,甚至没有返回非const引用的方法,您就不会遇到最后一个问题。

© www.soinside.com 2019 - 2024. All rights reserved.