1

This is similar to the previous question I asked but it is concerning a templated vector component-wise addition function.

I have a function called add which takes two vectors and stores their addition in an output vector. I am learning c++ so I am not sure how to make the type parameter to thrust::plus generic? The problem is that T is the type parameter for both device_vector and host_vector; which should be a type parameter for Vector.

template<typename Vector, typename T>
void add(const Vector& in1, const Vector& in2, Vector& out) {
    transform(in1.begin(), in1.end(), in2.begin(), out.begin(), thrust::plus<T>(c));   
}

The vector could be of two type:

device_vector<T>
host_vector<T>

My code doesn't compile as it is complaining about:

error: no instance of function template "add" matches the argument list

How can I play the plus function generic so it easily works with T of either device_vector<T> or host_vector<T>?

Community
  • 1
  • 1
jimjampez
  • 1,766
  • 4
  • 18
  • 29

2 Answers2

3

Use the container's value_type, and remove the second template parameter, as it cannot be deduced:

template<typename Vector>
void add(const Vector& in1, const Vector& in2, Vector& out) {
transform(in1.begin(), in1.end(), in2.begin(), out.begin(), 
          thrust::plus<typename Vector::value_type>(c)); 
}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • Perfect. It works now so thank you. I come from Java so the generics system is a bit different to what I am used to. – jimjampez Jan 29 '14 at 10:52
  • 2
    @jimjampez C++ templates are completely different to Java generics, so you might as well "unlearn what you have learned", at least temporarily :) – juanchopanza Jan 29 '14 at 10:53
  • LOL :) Do you have a book to recommend to learn C++ for a Java developer? – jimjampez Jan 29 '14 at 13:40
  • @jimjampez Not particularly for Java developers. Have a look at [this list of books](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – juanchopanza Jan 29 '14 at 19:06
1

Consult the docs of thrust::host_vector to see if it provides a nested typedef for its template parameters (such as std::vector<T> provides std::vector<T>::value_type identical to T). If it does, use it (as @juanchopanza's answer shows).

However, I tried looking at thrust docs briefly, and they didn't list such a typedef (unfortunate and surprising, but maybe true). If it indeed does not provide it, you have to use a template template parameter instead:

template<template <typename T, typename A> class Vector>
void add(const Vector<T, A>& in1, const Vector<T, A>& in2, Vector<T, A>& out) {
    transform(in1.begin(), in1.end(), in2.begin(), out.begin(), thrust::plus<T>(c));   
}

Note that you cannot just use T for the template template paremeter, you have to mirror the actual template parameters of the expected input class templates exactly. In C++11, you could help yourself a bit by using a variadic template:

template<template <typename T, typename... Other> class Vector>
void add(const Vector<T, Other...>& in1, const Vector<T, Other...>& in2, Vector<T, Other...>& out) {
    transform(in1.begin(), in1.end(), in2.begin(), out.begin(), thrust::plus<T>(c));   
}
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455