Подтвердить что ты не робот

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

У меня есть что-то вроде следующего кода:

   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; }

Я хотел бы переопределить его, используя предлагаемые вариационные шаблоны из предстоящего стандарта. Однако все примеры, которые я видел до сих пор в Интернете, похоже, являются примерами 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-значения вместо ссылок?

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

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

4b9b3361

Ответ 1

Я бы не использовал ссылки 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...); }

Ответ 2

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

Вы имеете в виду ссылки rvalue? Нет, я не вижу причин для них.

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

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

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

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

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 не является встроенным, в то время как каждая из его реализаций, вероятно, не будет содержать никаких реальных вызовов функций при выполнении встраивания вызовов inc_impl, но опять же нет гарантии.

Ответ 3

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

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

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

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