Calculate the average value of several values ​​using the function of the variation template

I am trying to write a function to determine the average value of an arbitrary number of arguments, all of which are of the same type. For training purposes, I am trying to do this using a variable-templated function.

This is what I still have:

template<typename T, class ... Args>
T Mean(Args ... args)
{
    int numArgs = sizeof...(args);
    if (numArgs == 0)
        return T();           // If there are no arguments, just return the default value of that type

    T total;
    for (auto value : args...)
    {
        total += value;
    }

    return total / numArgs;   // Simple arithmetic average (sum divided by total)
}

When I try to compile this (using MS Visual Studio 2013), I get the following compilation error:

error C3520: 'args' : parameter pack must be expanded in this context (test.cpp)

How to "unpack" a package of parameters args? I thought that was the purpose of the ellipses.

+2
source share
4 answers

:

template<typename T, class ... Args>
T Mean(Args ... args)
{
    int numArgs = sizeof...(args);
    if (numArgs == 0)
        return T();           // If there are no arguments, just return the default value of that type

    T total;
    for (auto value : {args...})
    {
        total += value;
    }

    return total / numArgs;   // Simple arithmetic average (sum divided by total)
}

std::initializer_list, .

+7

@ Drax - , , . , , . , , . :

#include <iostream>

using namespace std;

template<typename T>
T Mean(T head)
{
    return head;
}

template<typename T, class ... Args>
T Mean(T head, Args... args)
{
    auto N = sizeof...(Args);
    return (head + (N)*Mean(args...)) / (N + 1);  
}

int main(void)
{
    cout << Mean((double)1, (int)2, (float)4) << endl; // (double) 2.3333...
}

, ,

#include <iostream>

using namespace std;

template<typename T>
T Mean_wrapper(T head)
{
    return head;
}

// return type is the type of the head of param list
template<typename T, class ... Args>
T Mean_wrapper(T head, Args... args) 
{
    return head + Mean_wrapper(args...);   
}

template<typename T, class ... Args>
T Mean(T head, Args... args)
{
    return Mean_wrapper(head, args...) / (sizeof...(args) + 1);
}

int main(void)
{
    cout << Mean((double)10, (int)20, (float)30) << endl; // (double) 20

}
+2

, .

template <typename T, class... Args, std::size_t N = sizeof...(Args)>
T Mean(Args... args) {
  std::array<T, N> arr = {args...};
  if (N > 0) return std::accumulate(std::begin(arr), std::end(arr), T{}) / N;
  return T{};
}
+1

:

#include <iostream>
#include <type_traits>

namespace Detail {

    template <typename T, typename ... Args>
    struct Sum;

    template <typename T>
    struct Sum<T> {
        typedef T type;
        static type apply(T value) { return value; }
    };

    template <typename T, typename ... Args>
    struct Sum {
        typedef decltype(std::declval<T>() + std::declval<typename Sum<Args...>::type>()) type;
        static type apply(T a, Args ...args) {
            return a + Sum<Args...>::apply(args...);
        }
    };
} // namespace Detail

template <typename ... Args>
typename Detail::Sum<Args...>::type sum(Args ... args) {
    return Detail::Sum<Args...>::apply(args...);
}

template <typename ... Args>
typename Detail::Sum<Args...>::type mean(Args ... args) {
    return Detail::Sum<Args...>::apply(args...) / sizeof...(Args);
}


int main()
{
    // 2.5 / 2
    std::cout << mean(int(1), double(1.5)) << '\n';
    return 0;
}
+1

Source: https://habr.com/ru/post/1678677/


All Articles