C ++ template of atypical arithmetic parameter

I am trying to specialize a template as follows:

template<size_t _1,size_t _2> // workaround: bool consecutive = (_1 == _2 - 1)> struct integral_index_ {}; ... template<size_t _1> struct integral_index_<_1, _1 + 1> { // cannot do arithmetic? //struct integral_index_<_1, _2, true> { workaround }; 

however I get a compiler error

 the template argument list of the partial specialization includes a non -type argument whose type depends on a template parameter. 

what am I doing wrong? thanks

I put a workaround in the comments. Apparently I can't do arithmetic in the template specialization? seems controversial.

here is my final solution to the problem that needs to be solved. In principle, a sequential index requires only one multiplication.

 130 template<size_t _1,size_t _2, bool consecutive = (_1 == _2 - 1)> 131 struct integral_index_ { 132 template<typename T, typename U> 133 __device__ 134 static T eval(const T (&N)[4], const U &index) { 135 T j = index/N[_1]; 136 return ((index - j*N[_1])*range<0,_1>::multiply(N) + 137 j*range<0,_2>::multiply(N)); 138 } 139 }; 140 141 template<size_t _1,size_t _2> 142 struct integral_index_<_1, _2, true> { 143 template<typename T, typename U> 144 __device__ 145 static T eval(const T (&N)[4], const U &index) { 146 return index*range<0,_1>::multiply(N); 147 } 148 }; 149 150 template<size_t _1,size_t _2, typename T, typename U> 151 __device__ 152 T integral_index(const T (&N)[4], const U &index) { 153 return integral_index_<_1,_2>::eval(N, index); 154 } 
+6
c ++ parameters templates template-specialization
source share
5 answers

I submit my solution proposed by GMan

 130 template<size_t _1,size_t _2, bool consecutive = (_1 == _2 - 1)> 131 struct integral_index_ { 132 template<typename T, typename U> 133 __device__ 134 static T eval(const T (&N)[4], const U &index) { 135 T j = index/N[_1]; 136 return ((index - j*N[_1])*range<0,_1>::multiply(N) + 137 j*range<0,_2>::multiply(N)); 138 } 139 }; 140 141 template<size_t _1,size_t _2> 142 struct integral_index_<_1, _2, true> { 143 template<typename T, typename U> 144 __device__ 145 static T eval(const T (&N)[4], const U &index) { 146 return index*range<0,_1>::multiply(N); 147 } 148 }; 149 150 template<size_t _1,size_t _2, typename T, typename U> 151 __device__ 152 T integral_index(const T (&N)[4], const U &index) { 153 return integral_index_<_1,_2>::eval(N, index); 154 } 
+4
source share

Try something like this:

 template<size_t _1,size_t _2> struct integral_index_ {}; template<size_t _1> struct integral_index_2 : public integral_index_<_1, _1+1> { }; 
+1
source share

You can also transfer a condition from the main template to specialization. The trick is that although non-scoped type parameters in subexpressions are not allowed in non-type specialization arguments, they are allowed in type arguments

 template<bool C> struct bool_ { }; template<int _1, int _2, typename = bool_<true> > struct mapping { // general impl }; template<int _1, int _2> struct mapping<_1, _2, bool_<(_1 + 1) == _2> > { // if consecutive }; template<int _1, int _2> struct mapping<_1, _2, bool_<(_1 * 3) == _2> > { // triple as large }; 

Sometimes people use SFINAE for this. The following ::type calls, which exist only if the condition is true. If it is incorrect, it’s not, and SFINAE sorts the specialization.

 template<int _1, int _2, typename = void> struct mapping { // general impl }; template<int _1, int _2> struct mapping<_1, _2, typename enable_if<(_1 + 1) == _2>::type> { // if consecutive }; template<int _1, int _2> struct mapping<_1, _2, typename enable_if<(_1 * 3) == _2>::type> { // triple as large }; 

If enable_if is the next well-known pattern

 template<bool C, typename R = void> struct enable_if { }; template<typename R = void> struct enable_if<true, R> { typedef R type; }; 
+1
source share

I think the problem is that you are trying to specialize by value instead of type ...

0
source share

Something works for me here: use the default argument for _2 instead of specializing.

 template <size_t _1, size_t _2 = _1 + 1> struct integral_index_ {}; 

Does this look like what you want?

0
source share

All Articles