使用迭代器的C ++模板函数

时间:2014-06-05 17:43:46

标签: c++ templates

对不起,这一定是一个非常简单的问题...... 我是C ++的初学者,我正在尝试使用函数模板编写一个简单的快速排序函数。

#include <iostream>
#include <vector>
using namespace std;

template <class iterator, class val>
void move_to_front(iterator movethis, iterator leftend) {
  val temp = *movethis;          // hold the element being moved
  for (iterator i = movethis; i != leftend; i--) {
    *i = *(i-1);
  }                              // all other elements shift right
  *leftend = temp;               // put it back to the front
}

template <class iterator>
void qsort(iterator begin, iterator end) {
  iterator oldbegin = begin;
  for (iterator i = begin + 1; i != end; i++) {
    if (*i <= *begin) {
      move_to_front(i, begin);
      oldbegin++;
    }
  } // move elements smaller than or equal to the first element
    // to the left of the first element.
    // oldbegin indicates the first element, so it + 1 every time an 
    // element is moved to its left. 

  qsort(begin, oldbegin);
  qsort(oldbegin, end);
}

int main(int argc, char const *argv[]) {
  int test[] = {8,7,2,4,1,4,5,4,2};
  vector<int> ar(test, test+9);
  qsort(ar.begin(), ar.end());

  for (vector<int>::iterator i = ar.begin(); i != ar.end(); i++) cout << *i;
  return 0;
}

编译器抱怨

/Users/Larry_Li/Project Euler/foo.cpp:20:11: error: no matching function for call to 'move_to_front'
          move_to_front(i, begin);
          ^~~~~~~~~~~~~
/Users/Larry_Li/Project Euler/foo.cpp:31:7: note: in instantiation of function template specialization 'qsort<std::__1::__wrap_iter<int *> >' requested here
      qsort(ar.begin(), ar.end());
      ^
/Users/Larry_Li/Project Euler/foo.cpp:6:10: note: candidate template ignored: couldn't infer template argument 'val'
    void move_to_front(iterator movethis, iterator leftend) {
         ^
1 error generated.

我认为我在某种程度上错误地定义了模板...尤其是val中的template <class iterator, class val>部分,

请问如何让它发挥作用?

3 个答案:

答案 0 :(得分:2)

问题是编译器无法在此处推断出您的一个模板参数:

template <class iterator, class val>
void move_to_front(iterator movethis, iterator leftend) {
    val temp = *movethis;          // hold the element being moved

没有val类型的函数参数,因此编译器无法知道该类型应该是什么。但无论如何你根本不需要它。如果你有C ++ 11可用,你可以使用auto,正如Scooby建议的那样。否则,您可以使用std::iterator_traits从迭代器类型中获取值类型:

template <class iterator>
void move_to_front(iterator movethis, iterator leftend) {
    typename std::iterator_traits<iterator>::value_type temp = *movethis;

答案 1 :(得分:1)

这可能不会直接帮助,因为您似乎是故意重新发明轮子,和/或使用此方案来测试和扩展您的模板知识,而不是解决您的代码编写要解决的确切问题。但是,如果你想要做的只是实现move_to_front,请考虑std::rotate

#include <algorithm>

template <class iterator>
void move_to_front(iterator movethis, iterator leftend) {
    std::rotate(leftend, movethis, movethis + 1);
}

您可能还需要考虑更改参数的顺序以更符合STL,但这取决于您。请参阅live example(该示例使用C ++ 11,但该函数不需要它)。

答案 2 :(得分:0)

试试这个,假设你使用的是C ++ 11:

template <class iterator>
void move_to_front(iterator movethis, iterator leftend) {
  auto temp = *movethis;          // hold the element being moved
  for (iterator i = movethis; i != leftend; i--) {
    *i = *(i-1);
  }                              // all other elements shift right
  *leftend = temp;               // put it back to the front
}

但是,在我看来,我觉得你对所有的迭代器过于复杂。