Search code examples
c++tbb

error: use of class template 'blocked_range' requires template arguments


I'm using TBB library like this:

// Concurrency.hpp

#include <tbb/spin_mutex.h>
#include <tbb/mutex.h>
#include <tbb/parallel_for.h>
#include <tbb/parallel_reduce.h>

// Restrict templates to work for only the specified set of types
template<class T, class O = T>
using IntegerOnly = std::enable_if_t<std::is_integral<T>::value, O>;

// An extra helper template
template<class Fn, class I>
static IntegerOnly<I, void> loop_(const tbb::blocked_range<I> &range, Fn &&fn)
{
    for (I i = range.begin(); i < range.end(); ++i) fn(i);
}

// Calling TBB parallel-for by this template
template<class It, class Fn>
static void for_each(It from, It to, Fn &&fn, size_t granularity = 1)
{
    tbb::parallel_for(tbb::blocked_range{from, to, granularity}, // => Error happens at this line
                      [&fn, from](const auto &range) {
        loop_(range, std::forward<Fn>(fn));
    });
}

I'm receiving this error:

Concurrency.hpp:43:32: error: use of class template 'blocked_range' requires template arguments blocked_range.h:45:7: note: template is declared here

Did anybody run into this error before? How to resolve it?


Solution

  • tbb::blocked_range is a class template, and you are attempting to use class template argument deduction (CTAD) by omitting any explicit template arguments when constructing it.

    template<typename Value>
    class blocked_range {
    public:
        //! Type of a value
        /** Called a const_iterator for sake of algorithms that need to treat a blocked_range
            as an STL container. */
        typedef Value const_iterator;
    
        // ...
    
        //! Construct range over half-open interval [begin,end), with the given grainsize.
        blocked_range( Value begin_, Value end_, size_type grainsize_=1 ) // ...
    
        // ...
    };
    

    CTAD, however, is a C++17 feature, so if you are compiling with an earlier language version, you will need to specify the Value type template argument for the tbb::blocked_range class template. From above, we see that the Value type is expected as the iterator type, specifically the type of the first two arguments passed to its constructor, from and to in at the call site. Thus, you may modify your snippet as follows:

    // Calling TBB parallel-for by this template
    template<class It, class Fn>
    static void for_each(It from, It to, Fn &&fn, size_t granularity = 1)
    {
        tbb::parallel_for(tbb::blocked_range<It>{from, to, granularity},
                          [&fn, from](const auto &range) {
            loop_(range, std::forward<Fn>(fn));
        });
    }
    

    From what you mention in your comments this may be a portability issue, and you may be likely to run into more issues after this one, and may want to consider looking over your project's compilation flags, so to see if you could possibly compile using C++17 instead.