2015-01-12 185 views
0

编辑。请看我的评论。C++模板集合类型

我一直在努力与此一段时间了。我一直在编写一个mergesort例程,对矢量进行操作(坦率地说,重新发明了这个轮子),并且我一直在将迭代器传递给我的排序函数。在排序功能中,我创建了一个临时向量。现在,我希望它对任何元素类型进行操作,因为代码中没有特定于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) { 

如果它的任何利益,这是完整的清单我正在使用的当前快照 - 和合并()是一个我正在挣扎着。我已经多次与不同类型的改变的模板语法失败:

#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); 

^

+2

我已经花了很多年看着我认为是重复的链接问题。在决定问我的问题之前,我花了一段时间进行交易,我想我已经提出了一个非常具体的问题,并将相当数量的工作简单地提出来,足以证明它被视为一个完全不同的问题。我很欣赏我可能错过了模板的基本点,并且链接的答案对我没有多大帮助。我不是那种经验丰富的C++,如果有人能指出我正确的方向 –

回答

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,编译器会告诉你,它不能推断Tmerge被称为,因为::左侧的所有内容都是非推导的上下文。 merge为什么不应该被模板化为T而不是迭代器类型,或者实际上为什么它必须被限制为迭代器到std::vector(除了首先分配然后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()

Demo

+0

非常感谢你。这真的是我想要的。有人可能会争辩说,这不是我需要的哈哈。我设法得到了一点进一步,并且回来发布更新。我认为你的评论真的有助于澄清我的特定问题,而iterator_traits提示真的很有帮助!如果你有兴趣,这就是我想出的。它的功能,但有很多的行李! http://coliru.stacked-crooked.com/a/e7fc65269ab56a8e –