-2

I want to call a function which can accept a vector but i want to pass different type of vector to that function.

I have come across a function call like

print<int>(int_vector);
print<string>(string_vector);

here <int> and <string> are mention as what.

One more doubt is if i pass different type of vector also how can i take it in the function call. should i use void * ? then type cast it

  • 1
  • 4
    what you need are function templates http://en.cppreference.com/w/cpp/language/function_template – pm100 Jan 22 '18 at 17:28
  • 6
    You'd pretty much never use void* in C++. – DeiDei Jan 22 '18 at 17:29
  • You probably want either a template function or an overloaded function. – Jesper Juhl Jan 22 '18 at 17:31
  • 7
    ***should i use void * ? then type cast it*** No, never in c++. – drescherjm Jan 22 '18 at 17:33
  • 4
    If you want two different versions of the same function, dependent on argument type, an overload is likely what you need. That said, there are a plethora of things that can be done, including some you may not even consider (such as belaying passing the container itself in the first place and opting for templated iterators) dependent on what your *real* use-case is. This question needs a *lot* more context, including intent. – WhozCraig Jan 22 '18 at 17:36
  • 2
    @drescherjm unless you might find yourself in a position to implement a library that needs to do type erasure ... :) but that's a whole other dish. Your advice is strong. – bolov Jan 22 '18 at 17:40
  • @bolov came to say the same thing. It's bad advice to say _don't use a feature of the language_ .. rather _understand what pointers and pointer aliasing is, and understand there are numerous other ways to avoid use of a `void*`, templates are one such way_ – txtechhelp Jan 22 '18 at 17:43

5 Answers5

2

Sample of func template

#include <iostream>
#include <vector>

using namespace std;

template<typename T>
void foo(std::vector<T> vec)
{
   // do stuff with vector
}

int main() {
    std::vector<int> iv = {42};
    foo(iv);
    std::vector<string> sv = {"hello"};
    foo(sv);
    return 0;
}

There is an alternative if you know the exact types:

void foo(std::vector<int> v)
{}

void foo(std::vector<string> v)
{}

This is plain function overloading.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
pm100
  • 48,078
  • 23
  • 82
  • 145
  • 3
    The functions should use reference to const parameters instead of making useless copies of their arguments. – zett42 Jan 22 '18 at 17:51
  • i did exactly same but its giving error like "!expected identifier before ‘<’ token" – Tuhin Panda Jan 22 '18 at 18:36
  • what is the difference between class – Tuhin Panda Jan 22 '18 at 18:36
  • none - its just convention to use T for typename. You can say `template` if you want – pm100 Jan 22 '18 at 19:05
  • you should ask a new question posting your exact code with the exact error message – pm100 Jan 22 '18 at 19:06
  • void foo(std::vector vec) { // do stuff with vector } how to iterate the vector – Tuhin Panda Jan 23 '18 at 16:16
  • 2 ways. First is the original way supported by all c++ https://stackoverflow.com/questions/2395275/how-to-navigate-through-a-vector-using-iterators-c. Second is newer https://stackoverflow.com/questions/15027282/c-for-each-pulling-from-vector-elements – pm100 Jan 23 '18 at 16:24
1

The code is using template programming to make a generic function:

template <typename T>
void foo(T item){
    // do something to item of type T
}
void foo(int str); // Declare a certain type of template

Later you can use the function:

int x = 1;
foo<int>(x);

But in this case, because e.g. printf uses different formatting for different types, it might be wise to instead overload the functions. Overloading is the practise of naming functions similarly, but giving different arguments:

void foo(std::vector<int> v);
void foo(std::vector<string> v);
Felix
  • 2,548
  • 19
  • 48
1

What you want to use here is a templated function. Simples example relevant to your question would be:

// This line says that the function accepts one generic type
// which you will refer to as T
template <typename T>
// vector<T> means that the referenced type T will be of the type the vector, 
// you call this function with, is templated with
void print(const std::vector<T>& data) {
    // Here calling the operator[] will return the generic type T
    const T& element = data[0];
    for (unsigned i = 0; i < data.size(); ++i)
        std::cout << data[i] << std::endl;
}

This function would be used like this:

std::vector<int> vec = { 1, 2, 3 };
print(vec); 
// Note that you don't need to write the template type here
// because it is deduced from the type of vector

And the output will be:

1
2
3
Maroš Beťko
  • 2,181
  • 2
  • 16
  • 42
0

This concept is known as generic programming. In C++, you use templates to achieve this, and specifically a function template. If you want different types of lists with different types to be auto-deduced, or have a specific need for advanced templates, you can also use a template-template.

An example:

#include <iostream>
#include <vector>
#include <list>

template < template < class, class > class V, class T, class A >
void erase_value(V<T, A>& v, const T& t)
{
    typename V<T,A>::iterator s = v.begin();
    while (s != v.end()) {
        if ((*s) == t) { v.erase(s); break; }
        ++s;
    }
}

template < typename T >
void print_all(T begin, T end)
{
    for (; begin != end; ++begin) {
        std::cout << *begin << " ";
    }
    std::cout << std::endl;
}

template < typename T >
void print_all(const T& array)
{
    for (auto i : array) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
}

int main(int argc, char** argv)
{

    std::vector<std::string> strings {"123","321","ABC"};
    std::list<int> ints {123,321,5332};
    print_all(strings);
    print_all(ints);
    erase_value(strings, std::string("123"));
    erase_value(ints, 123);
    print_all(strings.begin(), strings.end());
    print_all(ints.begin(), ints.end());
    return 0;
}

Hope that can help.

txtechhelp
  • 6,625
  • 1
  • 30
  • 39
  • From your example I don't get why you would need template-template parameters. Your `erase_value()` [compiles aswell](https://wandbox.org/permlink/UYOw4Jv8uEZHO0QQ) when I change it to simple template parameter. – zett42 Jan 22 '18 at 18:04
  • 1
    @zett42 It's just to show that you _can_ utilize that for more advanced template programming, since it's not overtly clear what the OP is alluding to with regards to their template needs. – txtechhelp Jan 22 '18 at 18:12
0

I believe you're looking for ostream_iterator:

template <typename T>
void print(vector<T> arg){
    copy(cbegin(arg), cend(arg), ostream_iterator<T>(cout, " "));
}
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288