下面的示例是简陋的,因为我想了解这个概念。
假设我们想要一个数组的1元素view
。
我的问题是如何使它同时与const
和non-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);
}
}
以下作品:
#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
引用的方法,您就不会遇到最后一个问题。