A_K A_K -4 years ago 56
C++ Question

CUDA kernel "Only a single pack parameter is allowed" workaround?

The CUDA 7 standard regarding variadic global function templates states "only a single pack parameter is allowed." Is there an elegant workaround for this? I want to be able to do something like:

template<int... vals>
void RecursiveFunct() {

}

template<int... vals, typename T, typename... Args>
void RecursiveFunct(T t, Args... args) {
t.template call<vals...>();
RecursiveFunct<vals...>(args...);
}


I'm thinking I could wrap my pack of integers into something before passing them along but is it possible to do that in a way that is transparent to the caller of this code?

Answer Source

Not sure to understand your exactly limits but... I suppose that std::integer_sequence and a wrapper function to call call() can help you.

The following is a toy, but compilable, example that show what I mean.

struct foo
 {
   template <int ... vals>
   void call () const
    { std::cout << "- call " << sizeof...(vals) << std::endl; }
 };

template <typename IS>
void RecursiveFunct (IS const &)
 { }

template <typename T, int ... vals>
void wrapCall (T const & t, std::integer_sequence<int, vals...> const &)
 { t.template call<vals...>(); }


template<typename IS,  typename T, typename ... Args>
void RecursiveFunct (IS const & is, T t, Args... args)
 {
   wrapCall(t, is);
   RecursiveFunct(is, args...);
 }

int main ()
 {
   // print 5 times "- call 4"
   RecursiveFunct(std::integer_sequence<int, 2, 3, 5, 7>{},
                  foo{}, foo{}, foo{}, foo{}, foo{});
 }

Take in count that std::integer_sequence is a C++14 feature, so the preceding code needs (at least) a C++14 compiler.

But if you need to work with C++11, it's trivial to create a std::integer_sequence substitute.

By example

template <typename T, T ... ts>
struct myIntegerSequence
 { };
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download