Стоит ли полностью избегать использования const в шаблонном коде? - PullRequest
0 голосов
/ 30 октября 2018

Идея написания шаблонного кода заключается в написании универсального кода, который легко применим к некоторому универсальному типу T.

Идея использования const заключается в навязывании поведения объектам. Речь идет не только о том, чтобы сообщить пользователям, как они могут или не могут использовать объект, но и о том, чтобы сам объект сказал, что он не может измениться.

Эти две идеи, кажется, противоречат друг другу, не так ли? Как вы можете написать универсальный код, одновременно делая предположения о constness универсального типа? Конечно, во многих случаях вы можете быть в состоянии предсказать, что никогда не будете создавать экземпляр своего кода с типом, который не будет соответствовать вашему const -использованию, но представьте себе ужас, если вдруг обнаружите, что это не так, и пришлось бы копаться во всем вашем коде, чтобы удалить неправильно помещенные const?

Как мы решаем эту проблему? Разве мы не пишем const в шаблонном коде?

Ответы [ 3 ]

0 голосов
/ 30 октября 2018

Нет. const иногда о том, как определенный кусок кода будет использовать объект. void f(const T&) говорит, что f не изменит свой аргумент.

0 голосов
/ 30 октября 2018

Это интересный вопрос, хотя, честно говоря, у меня такое ощущение, что вы подходите к вопросу с некоторыми ложными посылками.

Во-первых, «универсальный» не означает, что универсальный код должен работать для любого типа T, который может существовать. Напротив, универсальный код обычно говорит вам, каковы требования к T, чтобы заставить код делать то, что он должен делать.

Например, T должно быть CopyAssignable и CopyConstructible, иначе вы не можете создать экземпляр std::vector<T>. T должен быть разрушаем, иначе вы не можете создать экземпляр std::optional<T>. И т. Д.

Seoncd, большинство const на самом деле относится к тому, как используется экземпляр (в отличие от того, чем на самом деле является экземпляр).

В качестве примера рассмотрим

template <typename T>
void print(const T& t) {
    std::cout << t;
}

Этот шаблон может быть создан только в том случае, если существует перегрузка operator<<, которая принимает const T&. Теперь, если тип не выполняет это требование, вы не можете создать экземпляр метода для этого типа.

Обратите внимание, что если какой-то тип Foo нарушает это требование, имея только

std::ostream& operator<<(std::ostream&, Foo&);

удаление const из print не является решением, потому что тогда внезапно было бы невозможно вызвать print с любым другим const T&. Заявление о том, что print не изменяет свои параметры, является полностью допустимым использованием const в шаблонном коде.

0 голосов
/ 30 октября 2018

const определенно имеет свое место. Возьмем, к примеру, vector::operator[], который имеет двойную перегрузку:

  1. T &operator[](size_t offset) дает вам изменяемую ссылку на данные.
  2. T const &operator[](size_t offset) const дает вам постоянную ссылку.

Когда я использую vector<int>, я могу захотеть иметь vector<int> const, и если он не нужен для второй перегрузки, я не смогу получить доступ ни к каким элементам в нем.

Нужно помнить, где разместить const s, но они также имеют свое место в коде шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...