У меня есть что-то как следующий код:
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 версия будет так же оптимально как оригинал? (я должен добавить встроенный или некоторые - такой?)
Я бы не стал использовать здесь ссылки на 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...); }
Какие гарантии дает новый предложенный стандарт в отношении проблемы рекурсивных вызовов функций, есть ли какие-то указания на то, что вышеприведенная вариативная версия будет такой же оптимальной, как и оригинальная? (следует ли добавить inline или что-то в этом роде?)
Стандарт не гарантирует, что оптимизация будет выполнена, он только определяет поведение и результат. Будет ли функция инлайн - проблема реализации.
Фактически, ключевое слово inline - это только подсказка компилятору, которая часто игнорируется, потому что компилятор может решить лучше.
Наконец, g++-4.5 полностью инлайнил все функции inc
на -O2
. Не знаю, то ли это, что вам нужно.
Должен ли я использовать 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 будет выполнен - но опять же, нет никакой гарантии.