Const вектор неконстантных объектов - PullRequest
24 голосов
/ 25 июля 2011

При определении функции в интерфейсе:

virtual void ModifyPreComputedCoeffs ( std::vector < IndexCoeffPair_t > & model_ ) = 0;

мы хотим указать, что вектор model_ не должен изменяться в том смысле, что операции push_back и т. Д. Не должны выполняться над вектором, но структура IndexCoeffPair_tобъекты в model_ могут быть изменены.Как мы должны это указать?

virtual void ModifyPreComputedCoeffs ( const std::vector < IndexCoeffPair_t > & model_ ) = 0;

не работает, я думаю.

Ответы [ 6 ]

17 голосов
/ 25 июля 2011

Вместо того, чтобы передавать вектор в функцию, сделайте то же, что и стандартная библиотека, и вместо этого передайте пару итераторов.

virtual void ModifyPreComputedCoeffs ( std::vector < IndexCoeffPair_t >::iterator & model_begin, std::vector < IndexCoeffPair_t >::iterator & model_end )
9 голосов
/ 25 июля 2011

Концепция константности C ++ корректно переоценивается IMO. То, что вы только что обнаружили, является одним из его больших ограничений: оно не масштабируется по составу. Чтобы иметь возможность создавать константный вектор неконстантных объектов, вам необходимо реализовать свой собственный векторный тип. Обратите внимание, что, например, даже стандартная библиотека должна была вводить новые типы для const_iterators.

Мое предложение состоит в том, чтобы использовать const -корректность там, где вас принуждают, а не везде, где вы можете. Теоретически, правильность const должна помочь программистам, но из-за синтаксиса это обходится очень дорого и очень примитивно (всего один бит, не масштабируется по составу, даже требует дублирования кода).

Кроме того, по моему опыту, эта предполагаемая большая помощь на самом деле не так уж велика ... большинство ошибок, которые она улавливает, относится к самому механизму правильности, а не к логике программы.

Когда-нибудь задумывались, почему большинство языков (включая языки, разработанные после C ++) не реализовали эту идею?

2 голосов
/ 13 мая 2013

Это, вероятно, в C ++ 14 как std :: dynarray .

На самом деле, если размер фиксирован во время компиляции, вы можете использовать std :: array.Но это, вероятно, более полезно для таких вещей, как встроенное программирование, буферы, матрицы и т. Д., Так как часто вы не знаете желаемый размер до времени выполнения или хотите, чтобы он был настраиваемым.

1 голос
/ 23 июня 2018

Вы можете попытаться создать const std::vector<YouType*>.Тогда вы не можете изменить вектор, но вы можете изменить объекты внутри вектора.Но будьте точны, потому что вы будете изменять исходные объекты, а не копии.

Использование интеллектуальных указателей или необработанных указателей зависит от ваших вариантов использования: у вас есть собственный вектор или только вектор наблюдателей.

1 голос
/ 25 июля 2011

Если вы можете изменить IndexCoeffPair_t, вы можете добавить некоторые константные функции-члены и использовать их для изменения некоторых своих членов, сделав их изменяемыми с помощью ключевого слова mutable.Однако это своего рода хак, поскольку теперь вы можете изменять содержимое любого const IndexCoeffPair_t.

Пример:

class IndexCoeffPair_t {
public:
    void changeX(int newVal) const {
        x = newVal;
    }

private:
    mutable int x;
};
0 голосов
/ 02 февраля 2019

Вот общая версия ответа MahlerFive:

template<typename T>
class Mutable {
    mutable T m_val;
public:
    constexpr Mutable(T const& val) : m_val(val) { }
    constexpr Mutable(T&& val) : m_val(val) { }

    // note: all member functions are `const`
    constexpr Mutable const& operator=(T const& val) const {
        m_val = val;
        return *this;
    }
    constexpr Mutable const& operator=(T&& val) const {
        m_val = val;
        return *this;
    }

    constexpr operator T&() const {
        return m_val;
    }
};

Затем вы можете использовать std::vector<Mutable<T>> const в своем коде, который в основном будет вести себя как положено.

...