【问题标题】:C++ template nontype parameter arithmeticC++ 模板非类型参数算术
【发布时间】:2010-04-11 03:04:39
【问题描述】:

我正在尝试通过以下方式专门化模板:

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.

我做错了什么? 谢谢

我将解决方法放在 cmets 中。显然我不能在模板专业化中做算术?似乎违反直觉。

这是我要解决的问题的最终解决方案。基本上,连续索引只需要一次乘法。

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 我想我可以使用额外的默认参数,bool consecutive = _1 == _2 - 1?
  • 我期待看到这个答案。它将提高我对语言的理解。
  • @aaa:不过,你希望做什么?
  • @aaa:啊,我明白了。你所拥有的似乎工作得很好,也很干净。 :) 您应该将其发布为答案并接受它。

标签: c++ templates parameters template-specialization


【解决方案1】:

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 }

【讨论】:

  • 你可以去掉静态的eval,只把值变成一个实际的静态变量。这样您就可以将值作为嵌套的::value 访问,而不是调用函数(在运行时仍然会发生)。
  • 根据multiply 的作用,也许该表达式甚至可以移动到enum 中。 (当然是在取消通话之后。)
【解决方案2】:

试试这样的:

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

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

【讨论】:

  • 我正在尝试专门研究第二个参数比第一个大一个的情况
  • 那么他就失去了他想要的效果。
  • 你好,我只是在原帖中使用第三个模板参数放了类似的东西
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • 您可以按价值专业化。问题在于专业化中的算术。
    【解决方案5】:

    这对我有用:使用 _2 的默认参数,而不是尝试专门化。

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

    这看起来像你想要的吗?

    【讨论】:

    • aaa 真的想写一个专门的模板版本,而不仅仅是一个默认参数。无论如何,他已经找到了一个很好的解决方法,即“布尔连续 = (_1 == _2 - 1)”技巧:)
    猜你喜欢
    • 2014-10-03
    • 1970-01-01
    • 2011-10-07
    • 2021-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    相关资源
    最近更新 更多