C ++ 11: Número de parâmetros de função de modelo variadic?

87

Como posso obter uma contagem do número de argumentos para uma função de modelo variável?

ie:

template<typename... T>
void f(const T&... t)
{
    int n = number_of_args(t);

    ...
}

Qual é a melhor maneira de implementar number_of_argso acima?

Andrew Tomazos
fonte
28
sizeof...(T).
R. Martinho Fernandes
21
@ R.MartinhoFernandes o formulário "Publique sua resposta" está alguns centímetros mais longe do final da página. ;)
kay
@ kay-SEisevil Não entendo por que seu comentário tem menos
Sapphire_Brick

Respostas:

103

Basta escrever isto:

const std::size_t n = sizeof...(T); //you may use `constexpr` instead of `const`

Observe que né uma expressão constante (ou seja, conhecida em tempo de compilação), o que significa que você pode usá-la onde a expressão constante for necessária, como:

std::array<int,   n>  a; //array of  n elements
std::array<int, 2*n>  b; //array of (2*n) elements

auto middle = std::get<n/2>(tupleInstance);

Observe que se você deseja calcular o tamanho agregado dos tipos empacotados (em oposição ao número de tipos no pacote), você deve fazer algo assim:

template<std::size_t ...>
struct add_all : std::integral_constant< std::size_t,0 > {};

template<std::size_t X, std::size_t ... Xs>
struct add_all<X,Xs...> : 
  std::integral_constant< std::size_t, X + add_all<Xs...>::value > {};

então faça isto:

constexpr auto size = add_all< sizeof(T)... >::value;

No C ++ 17 (e posterior), calcular a soma do tamanho dos tipos é muito mais simples usando a expressão de dobra :

constexpr auto size = (sizeof(T) + ...);

Espero que ajude.

Nawaz
fonte
9
+1 aprendeu duas coisas; sizeof...e constexpr. :)
Qix - MONICA ERA MISTURADA
1
Portanto, isso sizeof...realmente retorna o número de argumentos e não o tamanho do armazenamento combinado de todos os argumentos (como sizeofem uma matriz faria)?
panzi
@panzi: Sim. sizeof ...(T)retorna o número de tipos embalados T. Se você quiser calcular o tamanho agregado dos tipos compactados, terá que fazer algo assim: ideone.com/udggBk Também adicionei isso em minha resposta.
Nawaz
@panzi: o cálculo na minha resposta foi ligeiramente melhorado agora.
Nawaz
2
Com C ++ 17, para calcular o tamanho de tipos de arg individuais agora podemos usar expressões de dobra return (0 + ... + sizeof(t));
P0W