user425495
user425495

Reputation:

Variadic template function with a template function as an argument

I'm trying to compile the following:

#include <vector>
#include <array>

template <typename T>
void sort(T &container) {}

template <typename F, typename T, typename ...Tail>
void sort_containers(F sort_func, T &container, Tail &...tail) {
    sort_func(container);
    sort_containers(sort_func, tail...);
}

template <typename F, typename T>
void sort_containers(F sort_func, T &container) {
    sort_func(container);
}

int main() {
    std::vector<int> x = {1,2,3};
    std::vector<double> y = {1.0, 2.0, 3.0};
    std::array<char, 3> z = {{'d' , 'b', 'c'}};
    sort_containers(sort, x, y, z);
}

Which leads to the following compiler error with g++4.8:

error: no matching function for call to 
‘sort_containers(<unresolved overloaded function type>, 
std::vector<int>&, std::vector<double>&, std::array<char, 3u>&)’

I understand that I need to specify the template parameter for sort when passing it to sort_containers, but I'm not sure how this works in the presence of a variadic template function.

Upvotes: 1

Views: 284

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

template functions are function factories, not functions. They cannot be passed around directly.

Now, functors can be, and a relatively simple wrapper can turn an overload set of functions into a functor:

struct sort_functor {
   template<typename...Args>
   auto operator()(Args&&... args) const ->
   decltype(sort(std::forward<Args>(args)... ) )
   { return sort(std::forward<Args>(args)... ); }
};

which can be generated via macro, but not by template, because you cannot pass the overload set! You then pass sort_functor() to your other template.

#define MAKE_OVERLOAD_FUNCTOR( NAME ) \
  struct CONCAT( NAME, _functor ) { \
    template<typename...Args> \
    auto operator()(Args&&... args) const -> \
    decltype(NAME(std::forward<Args>(args)... ) ) \
    { return NAME(std::forward<Args>(args)... ) } \
  };

There is a proposal to make generating the above functor automagically via further abuse of the [] tokens.

Upvotes: 3

Related Questions