Должны ли все / большинство установочных функций в C ++ 11 быть написаны как шаблоны функций, принимающие универсальные ссылки?

Рассмотрим класс X с N переменные-члены, каждая из некоторых копируемого а также движимое тип и N соответствующие функции сеттера.
В C ++ 98 определение X скорее всего будет выглядеть примерно так:

class X
{
public:
void set_a(A const& a) { _a = a; }
void set_b(B const& b) { _b = b; }
...
private:
A _a;
B _b;
...
};

Сеттер-функции класса X выше может связывать как с lvalue, так и с rvalue аргументами. В зависимости от фактического аргумента, это может быть привести к созданию временного и будут в конечном итоге привести к назначению копии; В связи с этим, без копируемого типы не поддерживаются этим дизайном.

С C ++ 11 у нас есть семантика перемещения, идеальная пересылка и универсальные ссылки (терминология Скотта Мейерса), которые позволяют более эффективно и обобщенно использовать функции сеттера, переписав их следующим образом:

class X
{
public:
template<typename T>
void set_a(T&& a) { _a = std::forward<T>(a); }

template<typename T>
void set_b(T&& b) { _b = std::forward<T>(b); }
...
private:
A _a;
B _b;
...
};

Универсальные ссылки могут связываться с const/ не-const, volatile/ не-volatileи к любому конвертируемому типу в целом, избегая создания временных и передачи значений прямо в operator =, Non-копируемого, движимое типы теперь поддерживаются. Возможно, нежелательные привязки могут быть устранены либо через static_assert или через std::enable_if,

Итак, мой вопрос: как руководство по проектированию, Должны ли все (скажем, большинство) сеттер-функции в C ++ 11 быть написаны как шаблоны функций, принимающие универсальные ссылки?

Помимо более громоздкого синтаксиса и невозможности использования вспомогательных инструментов, подобных Intellisense, при написании кода в этих установочных функциях, есть ли существенные недостатки с гипотетическим принципом »написать функции-установщики как шаблоны функций, принимающие универсальные ссылки, когда это возможно«?

61

Решение

Вы знаете классы A и B, так что вы знаете, являются ли они подвижными или нет, и нужна ли эта конструкция в конечном итоге. Для чего-то вроде std::stringизменение существующего кода — пустая трата времени, если только вы не знаете, что у вас здесь проблемы с производительностью. Если вы имеете дело с auto_ptrтогда пришло время вырвать его и использовать unique_ptr,

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

void set_a(A a) { _a = std::move(a); }

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

36

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]