Я пытаюсь специализироваться, обрабатывают следующий путь по шаблону:
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
};
однако я получаю системную ошибку компилятора
the template argument list of the partial specialization includes a non
-type argument whose type depends on a template parameter.
что делает мое выполнение неправильно?спасибо
Я поместил обходное решение в комментарии. По-видимому, я не могу сделать арифметики в шаблонной специализации? кажется парадоксальным.
вот мое конечное решение в проблеме, которая будет решена. В основном последовательный индекс требует одного умножения только.
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 }
Я публикую мое решение, предложенное 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 }
Попробуйте сделать что-нибудь вроде этого:
template<size_t _1,size_t _2>
struct integral_index_ {};
template<size_t _1>
struct integral_index_2 : public integral_index_<_1, _1+1> {
};
Вот кое-что, что работает для меня: используйте аргумент по умолчанию для _2
вместо того, чтобы пытаться специализировать.
template <size_t _1, size_t _2 = _1 + 1>
struct integral_index_ {};
Похоже ли это на то, что вы хотите?
Я думаю, проблема в том, что вы пытаетесь специализироваться по значению, а не по типу ...
Вы также можете перенести условие из первичного шаблона в специализацию. Хитрость в том, что хотя параметры не-типа в подвыражениях не допускаются в аргументах специализации не-типа, они допускаются в аргументах типа
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
};
Иногда люди также используют SFINAE для этого. Ниже приводится обращение к ::type
, который существует только в том случае, если условие истинно. Если оно ложно, то тип отсутствует, а SFINAE сортирует специализацию.
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
};
С enable_if
является следующим хорошо известным шаблоном
template<bool C, typename R = void>
struct enable_if { };
template<typename R = void>
struct enable_if<true, R> { typedef R type; };