C ++模板非类型参数算术

时间:2010-04-11 03:04:40

标签: c++ templates parameters template-specialization

我试图通过以下方式专门化模板:

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 个答案:

答案 0 :(得分:4)

我发布我的解决方案是由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 :(得分:1)

尝试这样的事情:

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 :(得分:1)

您还可以将条件从主模板移动到专门化。诀窍是,虽然非类型特化参数中不允许子表达式中的非类型参数,但在类型参数中允许

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; };

答案 3 :(得分:0)

我认为问题在于你试图通过价值而不是类型来专攻......

答案 4 :(得分:0)

这是适合我的东西:使用_2的默认参数而不是尝试专门化。

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

这看起来像你想要的吗?