0

Say you would like to make iterative modifications to the elements of a container object and do something with the elements at each iteration. The code I came up with to do something like this:

#include <vector>
#include <iostream>

template <class InputIterator, class Operation, class Callback>
void transformAndTraverse(InputIterator begin, InputIterator end,  Operation op,  Callback cb) {
  InputIterator start = begin;
  while (begin != end) {
    op(begin);
    cb(start, end);
    ++begin;
  }
}

template <class InputIterator>
struct plotFnObject {
  void operator()(InputIterator begin, InputIterator end) {
    while (begin < end) {
      std::cout << *begin << " ";
      ++begin;
    }
    std::cout << std::endl;
  }
};

template <class InputIterator>
struct addTwoFnObject {
  void operator()(InputIterator idata) { *idata += 2; }
};

int main(int argc, char **argv) {
  typedef std::vector<int>::iterator vec_iter;
  std::vector<int> vec;
  vec.push_back(0);
  vec.push_back(0);
  vec.push_back(0);

#ifndef DEMO_COMPILE_ERROR
  // the below works
  transformAndTraverse(vec.begin(), vec.end(), addTwoFnObject<vec_iter>(), plotFnObject<vec_iter>());
#else
  // but this generates compilation errors
  addTwoFnObject<vec_iter> addtwo();
  plotFnObject<vec_iter> plot();
  transformAndTraverse(vec.begin(), vec.end(), addtwo, plot);
#endif
}

The trouble is that I get some difficult to understand compiler errors with the second form:

$ g++ testtemplate.cpp -DDEMO_COMPILE_ERROR
testtemplate.cpp: In function 'void transformAndTraverse(InputIterator, InputIterator, Operation, Callback) [with InputIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >, Operation = addTwoFnObject<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > (*)(), Callback = plotFnObject<__gnu_cxx::__normal_iterator<int*, std::vector<int> > > (*)()]':
testtemplate.cpp:44:60:   instantiated from here
testtemplate.cpp:8:5: error: too many arguments to function
testtemplate.cpp:9:5: error: too many arguments to function

$ g++ testtemplate.cpp
$

Why is the compiler OK with creating the function objects in-line, but not with creating them out of line and passing them?

$ g++ --version
g++ (GCC) 4.5.3
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

2 Answers 2

4

These are declarations of functions:

addTwoFnObject<vec_iter> addtwo();
plotFnObject<vec_iter> plot();

These are local variable instantiations:

addTwoFnObject<vec_iter> addtwo;
plotFnObject<vec_iter> plot;

You need to lose the extra parens at the end, otherwise the compiler complains that here you are trying to call the hypothetical function addtwo without providing an argument list:

transformAndTraverse(vec.begin(), vec.end(), addtwo, plot);
Sign up to request clarification or add additional context in comments.

Comments

2
addTwoFnObject<vec_iter> addtwo();
plotFnObject<vec_iter> plot();

declares functions named addtwo and plot, returning addTwoFnObject<vec_iter> and plotFnObject<vec_iter> respectively. Remove the ().

Google for "most vexing parse" for further information.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.