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.