4

When trying to compile this

template<typename type,const char* format>__device__ void d_prettyPrintVector(type* v, const unsigned int size)
{
    printf("\n ");
    for(int i=0; i<size; i++)
            printf(format, v[i]);
}
template<> void d_prettyPrintVector<float, "%4.1f ">(float*, const    unsigned int);
template<> void d_prettyPrintVector<int,   "%2d "  >(int*,   const unsigned int);
template<> void d_prettyPrintVector<char,  "%2d "  >(char*,  const unsigned int);
template<> void d_prettyPrintVector<bool,  "%d"    >(bool*,  const unsigned int);

and use it like this

d_prettyPrintVector(dc, blockDim.x);

I am getting

kernels.cu(104): error: no instance of function template "d_prettyPrintVector" matches the argument list
        argument types are: (int *, const unsigned int)

what is wrong?

Leo
  • 893
  • 1
  • 8
  • 9
  • update: when not using the function (only instantiating the template), I get the following errors: `kernels.cu:65: error: a cast to a type other than an integral or enumeration type cannot appear in a constant-expression` kernels.cu:65: error: template-id ‘d_prettyPrintVector >’ for ‘void d_prettyPrintVector(int*, unsigned int)’ does not match any template declaration` – Leo Mar 12 '15 at 02:45
  • 1
    possible duplicate of [Passing const char\* as template argument](http://stackoverflow.com/questions/3773378/passing-const-char-as-template-argument) – user657267 Mar 12 '15 at 02:46
  • Thank you, it is the same underlying problem, but the workarounds are different. Moreover, I saw that question when I asked mine, but I didn't see how it related. I am betting that there are newbies like me who will benefit from another example. – Leo Mar 12 '15 at 20:28

1 Answers1

4

I think you are not clear on how to use the type, float, int, etc., to grab an appropriate format string.

You can re-design your function to look something like:

 template <typename type>
 void d_prettyPrintVector(type* v, const unsigned int size)
 {
    printf("\n");
    for(int i=0; i<size; i++)
            printf(getFormatString<type>(), v[i]);
                   // ^^^ Get an format string appropriate for the type.
 }

That would be perfectly valid code if you had a function template:

 template <typename type> char const* getFormatString();

that had specializations for the types that you are interested in. In other words, the following should work:

 template <typename type> char const* getFormatString();

 template <typename type>
 void d_prettyPrintVector(type* v, const unsigned int size)
 {
    printf("\n");
    for(int i=0; i<size; i++)
            printf(getFormatString<type>(), v[i]);
                   // ^^^ Get an format string appropriate for the type.
 }

 template <> char const* getFormatString<float>() { return "%4.1f "; }
 template <> char const* getFormatString<int>()   { return "%2d "; }
 template <> char const* getFormatString<char>()  { return "%2d "; }
 template <> char const* getFormatString<bool>()  { return "%1d "; }

Now, you can use:

 int a[] = {1, 2};
 d_prettyPrintVector(a, 2);

 float b[] = {1.1f, 2.2f};
 d_prettyPrintVector(b, 2);

without any problem.

Extra

You can extend that idea to provide a lambda function as an argument to d_prettyPrintVector. The lambda function can return a custom format string that is more appropriate for a single use case.

Overload d_prettyPrintVector. Provide one that can take a lamba function as an argument.

 template <typename type, typename Format>
 void d_prettyPrintVector(type* v, const unsigned int size, Format format)
 {
     printf("\n");
     for(int i=0; i<size; i++)
             printf(format(), v[i]);
}

You can even implement the initial function using the new function so you don't have to repeat the details of how the items are printed.

template <typename type> char const* getFormatString();

template <typename type>
void d_prettyPrintVector(type* v, const unsigned int size)
{
   d_prettyPrintVector(v, size, [](){return getFormatString<type>();});
}

Now, in addition to the previous calls to print a and b, you can now use:

   // Define the format on the fly, using a lambda function.
   d_prettyPrintVector(a, 2, []() -> char const* {return "%4d ";});

   // Define the format on the fly, using a lambda function.
   d_prettyPrintVector(b, 2, []() -> char const* {return "%.6f ";});
R Sahu
  • 204,454
  • 14
  • 159
  • 270