Шаблон арифметики нетипизированных параметров шаблона C ++ - PullRequest
6 голосов
/ 11 апреля 2010

Я пытаюсь специализировать шаблон следующим образом:

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 }

Ответы [ 5 ]

4 голосов
/ 11 апреля 2010

Я публикую свое решение от 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 }
1 голос
/ 11 апреля 2010

Вы также можете переместить условие из основного шаблона в специализацию. Хитрость в том, что хотя нетипизированные параметры в подвыражениях не допускаются в аргументах нетипизированной специализации, они допускаются в аргументах типа

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, который только там, если условие выполняется. Если значение равно false, тип отсутствует и 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; };
1 голос
/ 11 апреля 2010

Попробуйте что-то вроде этого:

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

template<size_t _1>
struct integral_index_2 : public integral_index_<_1, _1+1> {
};
0 голосов
/ 11 апреля 2010

Вот кое-что, что работает для меня: используйте аргумент по умолчанию для _2 вместо попытки специализироваться.

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

Это похоже на то, что вы хотите?

0 голосов
/ 11 апреля 2010

Я думаю, проблема в том, что вы пытаетесь специализироваться по значению вместо типа ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...