SHAMELESS COPY [approved by its source]
kaczki parametr rozszerzać tylko w ściśle określonej liście kontekstów, a operator ,
nie jest jednym z nich. Innymi słowy, nie jest możliwe użycie rozszerzenia paczki do wygenerowania wyrażenia składającego się z szeregu podwyrażeń ograniczonych przez operatora ,
.
Praktyczna zasada brzmi: "Rozszerzenie może generować listę ,
-odparowanych wzorów, gdzie ,
jest ogranicznikiem listy." Operator ,
nie tworzy listy w sensie gramatycznym.
Aby wywołać funkcję dla każdego argumentu można użyć rekurencji (który jest podstawowym narzędziem w pole o zmiennej liczbie argumentów szablonu programisty):
#include <utility>
template<typename T>
void foo(T &&t){}
template<typename Arg0, typename Arg1, typename ... Args>
void foo(Arg0 &&arg0, Arg1 &&arg1, Args &&... args){
foo(std::forward<Arg0>(arg0));
foo(std::forward<Arg1>(arg1), std::forward<Args>(args)...);
}
auto main() -> int{
foo(1, 2, 3, "3");
}
UŻYTECZNE NON-KOPIOWANA INFO
Inną rzeczą, której prawdopodobnie nie widzisz w tej odpowiedzi, jest użycie specyfikatora &&
i std::forward
. W języku C++ specyfikator &&
może oznaczać jedną z dwóch rzeczy: referencje rvalue lub odwołania uniwersalne.
Nie przejdę do referencji rvalue, ale do kogoś pracującego z szablonami variadic; uniwersalne odniesienia to posłanie Boga.
Idealne Forwarding
Jednym z zastosowań std::forward
i uniwersalnych odniesień są doskonałe przekazywanie typów do innych funkcji.
W przykładzie, jeśli mijamy int&
do foo2
zostanie automatycznie zdegradowany do int
powodu podpisu generowanego foo2
funkcji po szablonu odliczenia a jeśli chciał wtedy naprzód ten arg
do innej funkcji, która go zmodyfikować ny odniesienie, otrzymasz niepożądane wyniki (zmienna nie zostanie zmieniona), ponieważ foo2
będzie przekazywać odniesienie do tymczasowego utworzonego przez przekazanie mu int
. Aby obejść ten problem, określamy funkcję przekazywania, która ma przyjmować dowolny typ typu odniesienia do zmiennej (wartość rVR lub). Następnie, aby upewnić się, że przekazujemy dokładnie ten typ przekazywany w funkcji przekazywania, używamy wtedy std::forward
, wtedy i tylko, a następnie zezwalamy na demotowanie typów; ponieważ jesteśmy teraz w punkcie, w którym ma to największe znaczenie.
Jeśli musisz, przeczytaj więcej na temat universal references i perfect forwarding; scott meyers jest świetny jako zasób.
Co jeśli 'Args' był pusty? – CoffeeandCode