template <typename Func, typename... Args>
static void WraperFunc(Func func, Args &&... args) {
SomeFunc(func, args...);
}
против
template <typename Func, typename... Args>
static void WraperFunc(Func func, Args ... args) {
SomeFunc(func, args...);
}
Что лучше и больше рекомендуется? Или есть альтернатива, которая лучше, чем оба?
Args &&
будет принимать lvalues и rvalues по ссылке и позволяет их пересылать при сохранении их оригинала категория стоимости. Я бы предпочел эту версию (и использовать std::forward
).
template <typename Func, typename... Args>
static void WraperFunc(Func func, Args &&... args) {
SomeFunc(func, std::forward<Args>(args)...);
// ^^^^^^^^^^^^ Use of forward
}
Обратите внимание на идиоматическое использование std::forward
, это не включает &&
из Args&&
,
Есть целый ряд статей по механике и использованию std::forward
и ссылка рушится, Вот и Скотт Мейерс классик на «пересылка (или универсальные) ссылки».
Первый, но вы должны пересылать свои аргументы во время расширения, используя std::forward<T>
, Это позволяет расширить ваш пакет параметров при правильном выводе ваших аргументов.
template <typename Func, typename... Args>
static void WraperFunc(Func func, Args &&... args)
{
// note that we use std::forward<Args>( args )... to perfect forward our arguments
SomeFunc(func, std::forward<Args>( args )...);
}
Например, скажем, у вас есть функция, объявленная следующим образом:
template <typename T>
void some_func( T& ) {}
Попытка использовать указанную функцию с временным значением или значением r не удастся:
some_func( 5 );
Это связано с тем, что 5 является константой, которую нельзя присвоить int&
,
Допустим, вы вызываете свою функцию со следующими аргументами:
void (*foo)(int, char, float) = /* ... */;
const int i = 0;
char j;
WraperFunc(foo, i, j, 0.42);
В первом случае это эквивалентно вызову этой функции:
void WraperFunc(void (*foo)(int, char, float), int i, char c, float j) { /* ... */ }
Во втором случае это эквивалентно вызову этой функции:
void WraperFunc(void (*foo)(int, char, float), const int& i, char& c, float&& j) { /* ... */ }
Второй рекомендуется, если вы хотите пересылать аргументы, избегая копий (но используйте std::forward
затем!)