user1672267
user1672267

Reputation: 175

Homework: C++ Templates With Vectors

I have to create a function that takes in a vector of unknown item types. Here is my code:

template <typename S>
void printVector(vector<S*> c){
   typename vector<S>::const_iterator A = c.begin();
   for (int A; A != c.end(); A++){
       cout<<c[A]<<" ";
   }
   cout<<endl;
}

In my main class here is my vector and function call:

vector<int> x;
int j=5;
for(int i=0;i<j;i++){
    x.push_back(num[i]);
}
printVector(x);

When I try to compile this code I get these errors:

exercise1_1.cpp: In function ‘int main()’:
exercise1_1.cpp:33:15: error: no matching function for call to ‘printVector(std::vector<int>&)
exercise1_1.cpp:33:15: note: candidate is:
exercise1_1.cpp:13:7: note: template<class S> void printVector(std::vector<S*>)

Upvotes: 0

Views: 333

Answers (2)

Daniel Castro
Daniel Castro

Reputation: 1290

There were some errors in your code. Let's look at them:

  • In the signature of printVector, you take a parameter of type vector<S*>. This means that, for a given type S, you take a vector of pointers to S. So, for example, if the type is int, you should 'send' a vector<int*>. In your example, you are attempting to 'send' a vector<int>, so the signature of printVector should look like this:

    template <typename S>
    void printVector(vector<S> c)
    
  • In your for loop, you are declaring the variable A again, as int. In the C++ standard library, you can access every item in a vector using iterators or just accessing them like an array. You were mixing both things.

If you want to loop using iterators, it should look like this:

typename vector<S>::const_iterator a = c.begin();
for (; a != c.end(); a++){
    cout<<*a<<" ";
}

Which means, for every item in the vector, print its value (notice I used *a because I'm using iterators).

Or using the index-based approach:

for (int i = 0; i < c.size(); i++){
   cout<<c[i]<<" ";
}

Also, as a common practice in C++ community, use a const reference when receiving variables of non-primitive types. This prevents that a copy of the object is performed, so it will probably be faster when dealing with huge collections. Example:

 void printVector(const vector<S>& c)

So here is a full working example:

#include <vector>
#include <iostream>

using namespace std;

template <typename S>
void printVector(const vector<S>& c){
   for (int i = 0; i < c.size(); i++){
       cout<<c[i]<<" ";
   }
   cout<<endl;
}

int main(int argc, char** args) {
    vector<int> x;
    int j=5;
    for(int i=0;i<j;i++){
        x.push_back(i);
    }
    printVector<int>(x); // Can be printVector(x); too
    return 0;
}

Upvotes: 3

Robᵩ
Robᵩ

Reputation: 168626

template <typename S>
void  printVector(const std::vector<S>& c){
   typename std::vector<S>::const_iterator A = c.begin();
   for (; A != c.end(); A++){
       std::cout<<*A<<" ";
   }
   std::cout<<"\n";
}

Fixes:

  • Your function was declared to take a vector<S*> but you obviously want it to take vector<S>.
    • Your main function invoked print_vector with an argument of std::vector<int>. Since an int is not an S* for any type of S, the template did not apply.
  • You have redeclared A when you intended to use only the first declaration.
  • You conflated indexed access to the vector with access through the iterator.
    • If you have an int: c[i]
    • If you have an iterator: *it

Less critical fixes:

  • Avoid using namespace std;
  • Never use std::endl when you mean "\n".
  • You should pass the parameter by const reference, not by value

Upvotes: 2

Related Questions