1

En python existen funciones de lista de argumentos flexible que tiene la capacidad de recibir un numero variable de argumentos.

La siguiente función calcula el promedio de varios números:

def promedio(*args):
    suma=0
    for n in args:
        suma+=n
    return suma/len(args)

print(promedio(2,3,2))
print(promedio(4,6,8,3))
print(promedio(324,2432,3243,23672,265,452,234,))

Es posible escribir la misma función en C++?

JosephGen
  • 301
  • 1
  • 9

2 Answers2

5

Lo que estás buscando son las fold expressions de C++17:

template <typename ... ARGS>
auto promedio(ARGS ... args)
{
    return (args + ...) / sizeof...(args);
//         ^^^^^^^^^^^^   ^^^^^^^^^^^^^^^
//               \                \___ cuenta todos los argumentos.
//                \
//                 \___ aplica el operador de suma a todos los argumentos.
}

Si llamas a la función promedio con (1, 2, 3, 4) el compilador generará el siguiente código:

int promedio(int arg1, int arg2, int arg3, int arg4)
{
    return (arg1 + (arg2 + (arg3 + arg4))) / 4;
}
PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82
3

Se llaman templates variadicos. Basicamente recibes un paquete de argumentos, y los vas "pelando" uno a uno. Aquí tienes un ejemplo creando tu función:

#include <iostream>

float suma(float val) {
    return val;
}

template <class ...Args>
float suma(float val, Args ...args) {
    return val + suma(args...);
}


template <class ...Args>
float promedio(Args... args) {
    return suma(args...)/sizeof...(args);
}

int main(void) {
    std::cout << promedio(1.0f, 2.0f, 3.0f);
    return 0;
}

Entonces el compilador va a generar las funciones para 3, 2 y 1 argumentos, y va a colocar las llamadas así:

#include <iostream>

float suma(float val)
{
  return val;
}


template <class ...Args>
float suma(float val, Args ...args) {
    return val + suma(args...);
}

/* First instantiated from: insights.cpp:15 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
float suma<float, float>(float val, float __args1, float __args2)
{
  return val + suma(__args1, __args2);
}
#endif


/* First instantiated from: insights.cpp:9 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
float suma<float>(float val, float __args1)
{
  return val + suma(__args1);
}
#endif



template <class ...Args>
float promedio(Args... args) {
    return suma(args...)/sizeof...(args);
}

/* First instantiated from: insights.cpp:19 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
float promedio<float, float, float>(float __args0, float __args1, float __args2)
{
  return suma(__args0, __args1, __args2) / static_cast<float>(3);
}
#endif


int main()
{
  std::cout.operator<<(promedio(1.0F, 2.0F, 3.0F));
  return 0;
}

Este lo puedes ver en cppInsights.

BetaM
  • 30,571
  • 7
  • 32
  • 50
Pablochaches
  • 2,505
  • 1
  • 5
  • 21
  • Puedes simplificar mucho la función con *fold expressions*: [`template float promedio(Args... args) { return (args + ...) / sizeof...(args); }`](https://tio.run/##RY3NCoMwEITP5ikWejFY0/8e1Ap9lBCjBPJHEi8VX73pWgo9fCwzuzsjvK@F5nbKeaes0PMgoVMupiC56QlJ0njNE5p4FSMwxp5hij2M2vEEPjgjB@XKzcQdcJwUFggyzcFCuWmotjcKB4jqJd2I4uvTFlZClE1guLIlJQspYhqaRrg5Qdf9009sD2fkglyRG3JntCXFr@fYkjXntxg1n2KuMeUhqurMPw "C++ (clang) – Try It Online") – PaperBirdMaster Apr 15 '21 at 10:32