Generar una secuencia de ceros en tiempo de compilación


Tengo el siguiente problema:

template< size_t... N_i >
class A
{
  public:

    // ...

    void foo()
    {
      bar( /* 0,...,0 <- sizeof...(N_i) many */);
    }
};

Quiero llamar a una función bar y pasarle sizeof...(N_i) muchos argumentos que son todos ceros, por ejemplo, bar(0,0,0) en el caso sizeof...(N_i) == 3. ¿Cómo se puede aplicar esto?

Author: abraham_hilbert, 2016-10-24

3 answers

bar(((void)N_i, 0)...);

El operador de coma descartará N_i, produciendo solo el valor del operando de la derecha (0). El lanzamiento es para evitar una advertencia sobre N_i ser descartado.

 61
Author: Columbo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-24 12:46:49

A pesar de la indudablemente interesante respuesta de @Columbo , quiero sugerir otra solución viable basada en constexpr variables de plantilla'd:

 #include <cstddef> 

 template<std::size_t, std::size_t V>
 constexpr std::size_t repeat_value = V;

 template<std::size_t... N_i>
 class A {
     template<typename... Args>
     void bar(Args&&...) { }

 public:   
      void foo() {
           // repeat N_i times value 0
           bar(repeat_value<N_i, 0>...);
      }
 };

 int main() {
      A<0, 1, 2, 3, 4> a;
      a.foo();
 }

Me resulta más fácil de leer al menos, incluso si es malo en términos de rendimiento en tiempo de compilación.


Puedes generalizarlo fácilmente de la siguiente manera:

template<std::size_t, typename T, T V>
constexpr T repeat_value = V;

La invocación en el caso específico es la siguiente:

bar(repeat_value<N_i, int, 0>...);
 8
Author: skypjack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:07

También puedes usar plantillas para simular algo similar. Esta es una solución muy básica y solo creará una lista de 0s, pero podría ampliarse para generar otras secuencias si se desea.

template <size_t Unused>
struct Wrap {
  static constexpr size_t value = 0;
};

template <size_t... N_i>
class A {
public:
    void foo() {
        bar(Wrap<N_i>::value...);
    }
};

Que simplemente se expandirá en una lista de ceros del mismo tamaño que los argumentos N_i. Es cierto que la interfaz es ligeramente diferente.

Para un ejemplo completo, que muestra los valores de los elementos que recibe bar, vea aquí: Ejemplo en vivo

 2
Author: RobClucas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-24 14:35:47