C ++模板集合类型

时间:2015-01-12 15:02:17

标签: c++ templates vector collections std

编辑。请看我的评论。

我现在已经挣扎了一段时间了。我一直在编写一个对向量进行操作的mergesort例程(无可否认地重新发明轮子),并且我已经将迭代器传递给了我的sort函数。在sort函数中,我创建了一个临时向量。现在,我希望它可以在任何元素类型上运行,因为代码中没有特定于int / double等等的东西。我似乎无法使我的模板定义工作。我尝试了很多不同的方法。如果有人可能会看到我在下面写的小片段,并告诉我如何让它工作,以便我可以接受vector :: iterator作为函数参数,然后声明并使用函数内的向量本身,我真的很感激。

#include <vector>
using namespace std;

template <typename T>
void test(vector<T>::iterator myiter) {
  typename vector<T> myvec;
}

这是我的编译时错误:

$ make tmpl
g++  -Wall -ggdb --std=c++11   tmpl.cc   -o tmpl
tmpl.cc:5:22: error: variable or field ‘test’ declared void
 void test(vector<T>::iterator myiter) {
                      ^
tmpl.cc:5:31: error: expected ‘)’ before ‘myiter’
 void test(vector<T>::iterator myiter) {

如果有任何兴趣,这是我正在使用的完整列表的当前快照 - 而merge()是我正在努力解决的问题。我使用各种类型的失败多次更改了模板语法:

#include <iostream>
#include <vector>

template <typename Iter>
void print_collection(Iter start, Iter end) {
  std::cout << "collection = { ";
  for(; start != end; ++start) {
    std::cout << *start << ", ";
  }
  std::cout << "};" << std::endl;
}


template <typename T>
void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
  std::vector<T> temp;
  std::vector<T>::iterator i, j;
  i = start;
  j = pivot;
  while(i != pivot && j != end) {
    if(*i <= *j) {
      temp.push_back(*i);
      ++i;
    } else if(*i > *j) {
      temp.push_back(*j);
      ++j;
    }
  }
  for(; i != pivot; ++i) {
    temp.push_back(*i);
  }
  for(; j != end; ++j) {
    temp.push_back(*j);
  }
  i = start;
  j = temp.begin();
  for(; i != end, j != temp.end(); ++i, ++j) {
    *i = *j;
  }
}


template <typename Iter>
void merge_sort(Iter start, Iter end, int len) {
  if(len <= 1) {
    return;
  }
  int odd, left_len, right_len;
  Iter pivot;
  odd = len % 2;
  left_len = (len / 2) + odd;
  pivot = start + left_len;
  right_len = len / 2;

  merge_sort(start, pivot, left_len);
  merge_sort(pivot, end, right_len);
  merge(start, pivot, end, left_len, right_len);
}


int main(void) {
  std::vector<double> vl = { 1.1, 9.1, 2.1, 8.1, 3.1, 7.1, 4.1, 6.1, 5.1, 0.1 };
  print_collection(vl.begin(), vl.end());
  merge_sort(vl.begin(), vl.end(), vl.size());
  print_collection(vl.begin(), vl.end());
  return 0;
}

以及完整列表中的编译错误:

$ make vec
g++  -Wall -ggdb --std=c++11   vec.cc   -o vec
vec.cc:39:28: error: variable or field ‘merge’ declared void
 void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
                            ^
vec.cc:39:37: error: expected ‘)’ before ‘start’
 void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
                                     ^
vec.cc:39:69: error: expected ‘)’ before ‘pivot’
 void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
                                                                     ^
vec.cc:39:101: error: expected ‘)’ before ‘end’
 void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
                                                                                                     ^
vec.cc:39:106: error: expected primary-expression before ‘int’
 void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
                                                                                                          ^
vec.cc:39:120: error: expected primary-expression before ‘int’
 void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
                                                                                                                        ^
vec.cc: In instantiation of ‘void merge_sort(Iter, Iter, int) [with Iter = __gnu_cxx::__normal_iterator<double*, std::vector<double> >]’:
vec.cc:88:45:   required from here
vec.cc:81:47: error: ‘merge’ was not declared in this scope
   merge(start, pivot, end, left_len, right_len);

^

1 个答案:

答案 0 :(得分:1)

两个问题:

  1. std::vector<T>::iterator的所有实例都应为typename std::vector<T>::iterator,因为它取决于模板参数。原因在规范问题Where and why do I have to put the "template" and "typename" keywords?

    中进行了解释

    如果您compile with Clang

    ,此处的错误消息会更加清晰
    main.cpp:15:12: error: missing 'typename' prior to dependent type name 'std::vector<T>::iterator'
    void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
               ^~~~~~~~~~~~~~~~~~~~~~~~
               typename 
    main.cpp:15:44: error: missing 'typename' prior to dependent type name 'std::vector<T>::iterator'
    void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
                                               ^~~~~~~~~~~~~~~~~~~~~~~~
                                               typename 
    main.cpp:15:76: error: missing 'typename' prior to dependent type name 'std::vector<T>::iterator'
    void merge(std::vector<T>::iterator start, std::vector<T>::iterator pivot, std::vector<T>::iterator end, int left_len, int right_len) {
                                                                               ^~~~~~~~~~~~~~~~~~~~~~~~
                                                                               typename 
    main.cpp:17:3: error: missing 'typename' prior to dependent type name 'std::vector<T>::iterator'
      std::vector<T>::iterator i, j;
      ^~~~~~~~~~~~~~~~~~~~~~~~
      typename 
    
  2. Once you fix that,编译器会告诉您在调用T时无法推断merge,因为::左侧的所有内容都是merge是一个非推断的上下文。没有真正的理由为什么T应该在std::vector而不是迭代器类型上进行模板化,或者为什么必须将迭代器限制为pivot(除了temp.begin()之外的原因。首次分配j然后将template <typename Iter> void merge(Iter start, Iter pivot, Iter end, int left_len, int right_len); 分配给std::vector<T>时的代码,可以通过添加其他变量轻松修复):

    T

    但是你创建了一个std::iterator_traits作为临时,所以我们现在需要弄清楚typedef typename std::iterator_traits<Iter>::value_type T; 或迭代器的值类型。这样做的方法是通过i != end, j != temp.end()

    i != end && j != temp.end()
  3. 方面问题:{{1}}作为循环条件毫无意义。大概你的意思是{{1}}。

    Demo