传递函数对象时编译错误

时间:2011-10-19 12:22:49

标签: c++ templates

假设您希望对容器对象的元素进行迭代修改,并在每次迭代时对元素执行某些操作。我提出的代码就是这样做的:

#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
}

麻烦的是我用第二种形式得到了一些难以理解的编译器错误:

$ 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
$

为什么编译器可以在线创建函数对象,但不能在线外创建并传递它们?

$ 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 个答案:

答案 0 :(得分:4)

这些是函数的声明:

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

这些是局部变量实例化:

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

你需要在最后丢失额外的parens,否则编译器会抱怨你在这里尝试调用假设函数addtwo而不提供参数列表:

transformAndTraverse(vec.begin(), vec.end(), addtwo, plot);

答案 1 :(得分:2)

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

声明名为addtwoplot的函数,分别返回addTwoFnObject<vec_iter>plotFnObject<vec_iter>。删除()。

Google提供“最令人烦恼的解析”以获取更多信息。