Как правильно использовать ссылки с шаблонами variadic

У меня есть что-то как следующий код:

   template<typename T1, typename T2, typename T3, typename T4>
   void inc(T1& t1, T2& t2, T3& t3, T4& t4) { ++t1; ++t2; ++t3; ++t4; }

   template<typename T1, typename T2, typename T3>
   void inc(T1& t1, T2& t2, T3& t3) { ++t1; ++t2; ++t3; }

   template<typename T1, typename T2>
   void inc(T1& t1, T2& t2) { ++t1; ++t2; }

   template<typename T1>
   void inc(T1& t1) { ++t1; }

Я хотел бы повторно реализовать его с помощью предложенных шаблонов variadic из предстоящего стандарта. Однако все примеры, которые я видел до сих пор онлайн, кажется, printf как примеры, различие здесь, кажется, использование ссылок. Я придумал следующее:

inline void inc() { }

template<typename T>
inline void inc(T&& t) { ++t; }

template<typename T,typename ... Args>
inline void inc(T&& t, Args&& ... args) { ++t; inc(args...); }

То, что я хотел бы знать:

  • Я должен использовать r-значения вместо ссылок?

  • Возможные подсказки или подсказки относительно того, как выполнить то, что я хочу правильно.

  • Какие гарантии новый предложенный стандарт предоставляет в отношении проблемы вызовов рекурсивной функции, есть ли некоторый признак, что вышеупомянутое variadic версия будет так же оптимально как оригинал? (я должен добавить встроенный или некоторые - такой?)

13
задан River 21 October 2017 в 21:37
поделиться

3 ответа

Я бы не стал использовать здесь ссылки на rvalue, потому что это позволит вам привязываться к rvalues, что может позволить такой бессмысленный код, как:

inc(1);

Поэтому я бы придерживался обычных ссылок:

template<typename T>
void inc(T& t) { ++t; }

template<typename T,typename ... Args>
void inc(T& t, Args& ... args) { ++t; inc(args...); }
12
ответ дан 2 December 2019 в 00:17
поделиться

Какие гарантии дает новый предложенный стандарт в отношении проблемы рекурсивных вызовов функций, есть ли какие-то указания на то, что вышеприведенная вариативная версия будет такой же оптимальной, как и оригинальная? (следует ли добавить inline или что-то в этом роде?)

Стандарт не гарантирует, что оптимизация будет выполнена, он только определяет поведение и результат. Будет ли функция инлайн - проблема реализации.

Фактически, ключевое слово inline - это только подсказка компилятору, которая часто игнорируется, потому что компилятор может решить лучше.

Наконец, g++-4.5 полностью инлайнил все функции inc на -O2. Не знаю, то ли это, что вам нужно.

1
ответ дан 2 December 2019 в 00:17
поделиться

Должен ли я использовать r-значения вместо ссылок?

Вы имеете в виду ссылки на r-значения? Нет, я не вижу причин для этого.

Возможные подсказки или намеки на то, как правильно выполнить то, что я хочу.

Вы уже там. Ваш код должен делать то, что вы хотите.

Какие гарантии дает новый предложенный стандарт в отношении вопроса рекурсивных вызовов функций, есть ли какие-то указания на то, что вышеприведенная вариативная версия будет такой же оптимальной, как и оригинальная? (нужно ли добавить inline или что-то в этом роде?)

Стандарт C++ не гарантирует никакого инлайнинга. Вы можете проверить, что генерирует компилятор. Если вы хотите, чтобы все было встроено - включая самый верхний вызов inc - вы можете поместить inline в обе функции в качестве запроса. Если вы хотите что-то вроде вашего невариативного шаблона, вы можете обернуть его так:

inline void inc_impl() {}

template<typename T, typename...U>
inline void inc_impl(T& t, U&...u) { ++t; inc_impl(u...); }

template<typename...T>
void inc(T&...t) { inc_impl(t...); }

Теперь inc не является inline, а каждая из его реализаций, вероятно, не будет содержать реальных вызовов функций, когда инлайнинг вызовов inc_impl будет выполнен - но опять же, нет никакой гарантии.

2
ответ дан 2 December 2019 в 00:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: