Работает следующее:
#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
a const Array
, вы также должны указать const Array
в качестве аргумента шаблона.
Но затем вернуть не const
ссылка с value()
больше не работает, поэтому мы отключаем эту функцию с SFINAE, если тип массива const
.
PS: у вас не будет последней проблемы, если ваш класс с именем View
действительно был тем, чего можно было ожидать в представлении, то есть немодифицированным и даже не имел метода, возвращающего не const
ссылку.