Search code examples
c++templatesc++11openmpstd-function

std::function which returns any summable type?


My graph data structure for parallel algorithms has the following iterator method:

/**
 * Iterate in parallel over all nodes of the graph and call handler (lambda closure).
 */
void Graph::parallelForNodes(std::function<void(node)> handle) {
    #pragma omp parallel for
    for (node v = 0; v < z; ++v) {
        // call here
        handle(v);
    }
}

I could have declared the handle function as a template parameter, but I thought the preferred way in C++11 is to use std::function.

Now I want to perform a parallel reduction using OpenMP with such an iterator. The return values of each call to handle are reduced to a sum. With function templates, this looks like:

template<typename L>
inline double Graph::parallelSumForNodes(L handle) {
    double sum = 0.0;
#pragma omp parallel for reduction(+:sum)
    for (node v = 0; v < z; ++v) {
        // call here
        if (exists[v]) {
            sum += handle(v);
        }
    }
    return sum;
}

What is the equivalent using std::function? Can I define the type of handle to return double or int (because the body of the function works with both).


Solution

  • Perhaps a two parameter member function, along the lines of std::accumulate?

    template<typename Handle, typename Accumulator>
    Accumulator Graph::parallelSumForNodes(Handle handle, Accumulator sum) 
    {
    #pragma omp parallel for reduction(+:sum)
        for (node v = 0; v < z; ++v) {
            // call here
            if (exists[v]) {
                sum += handle(v);
            }
        }
        return sum;
    }
    

    Note that this has the same caveat as std::accumulate: you have to be careful with the type of the accumulator you pass it.