Question

In this rather contrived example, I'm trying to pass a function template to my function, and want my function to instantiate the function template internally. In essence, I don't want the user to know the types, and workings of my function, but just be able to pass a function template for me to instantiate myself. Self contained example (that doesn't compile):

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

template <template <typename InputIt, typename OutputIt> class CopyFunc>
void transferWith( CopyFunc<std::vector<int>::const_iterator,
                            std::back_insert_iterator<std::vector<int>>> const& func )
{
    std::vector<int> source{1, 2, 3, 4, 5, 6, 7};
    std::vector<int> sink;

    func(source.begin(), source.end(), std::back_inserter(sink));

    for (auto&& e : sink)
    {
        std::cout << e << std::endl;
    }
}

int main(int argc, char const *argv[])
{

    // I want to pass just the function template in,
    // and instantiate it internally
    transferWith(std::copy);

    return 0;
}

This fails to compile on gcc-4.7.2 as expected, with the following errors:

main.cpp|25 col 27 error| no matching function for call to ‘transferWith(<unresolved overloaded function type>)’
main.cpp|8 col 6 error| note: template<template<class InputIt, class OutputIt> class CopyFunc> void transferWith(const CopyFunc<__gnu_cxx::__normal_iterator<const int*, std::vector<int> >, std::back_insert_iterator<std::vector<int> > >&)
main.cpp|25 col 27 error| note:   couldn't deduce template parameter ‘template<class InputIt, class OutputIt> class CopyFunc’

Are there any tricks or indirections one can pull to get around this?

Thank you.

Was it helpful?

Solution

Just for completeness, here's an example of the functor approach:

#include <algorithm>
#include <vector>
#include <iostream>

struct Copy {
  template <typename InputIter, typename OutputIter>
  OutputIter operator()(InputIter i1, InputIter i2, OutputIter o1) {
    return std::copy(i1, i2, o1);
  }
};

template <typename CopyFunctor> 
void foo(CopyFunctor cf) {
  std::vector<int> v1 = {3, 1, 4}; 
  std::vector<int> v2(v1.size());

  cf(v1.begin(), v1.end(), v2.begin());

  for (auto i : v2) {
    std::cout << i << ' ';
  }
}

int main() {
  foo(Copy());  // displays "3 1 4"
}

OTHER TIPS

Are there any tricks or indirections one can pull to get around this?

Yes. Pass a functor object with template operator()().

The code will look exactly like the version in Bart's answer.

Would something along the lines

template <template <typename InputIt, typename OutputIt> class CopyFunc> void transferWith()
{
    std::vector<int> source{1, 2, 3, 4, 5, 6, 7};
    std::vector<int> sink;

    CopyFunc<std::vector<int>::const_iterator, std::vector<int>::iterator>(source.begin(), source.end(), std::back_inserter(sink));

    for (auto&& e : sink)
    {
        std::cout << e << std::endl;
    }
}

called as:

transferWith<std::copy>();

do?

I am not promising this will compile out of a box...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top