2010-04-11 23 views
6

Tôi cố gắng để chuyên template theo cách sau:C++ template không do type tham số số học

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

Tuy nhiên tôi nhận được biên dịch báo lỗi

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

những gì tôi làm sai? cảm ơn

Tôi đưa ra cách giải quyết trong nhận xét. Rõ ràng tôi không thể làm số học trong chuyên môn mẫu? có vẻ phản trực giác.

đây là giải pháp cuối cùng của tôi trong vấn đề cần giải quyết. Về cơ bản, chỉ số liên tiếp chỉ yêu cầu một phép nhân.

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

bức tranh lớn hơn một chút sẽ giúp đây. Bạn phải làm một chút thay đổi thiết kế để có được hiệu ứng tương tự. Ngoài ra, các số dòng có xu hướng cản trở. :) – GManNickG

+0

@GMan Tôi cho rằng tôi có thể sử dụng đối số mặc định thêm, 'bool liên tiếp = _1 == _2 - 1'? – Anycorn

+0

Tôi rất mong được nhìn thấy câu trả lời này. Nó sẽ nâng cao hiểu biết của tôi về ngôn ngữ. – Omnifarious

Trả lời

4

Tôi gửi bài giải pháp của tôi là đề nghị của 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

Bạn có thể loại bỏ 'eval' tĩnh và chỉ biến giá trị thành biến tĩnh thực tế. Bằng cách đó bạn có thể truy cập giá trị như một 'giá trị lồng nhau' thay vì gọi một hàm (mà vẫn xảy ra khi chạy). –

+0

Tùy thuộc vào 'multiply' làm gì, có lẽ biểu thức đó thậm chí có thể được chuyển vào một' enum'. (Sau khi loại bỏ các cuộc gọi, tất nhiên.) – Potatoswatter

1

Hãy thử một cái gì đó như thế này:

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

Tôi đang cố gắng để chuyên các trường hợp đối số thứ hai là một lớn hơn lần đầu tiên – Anycorn

+0

Sau đó, anh ta mất hiệu ứng mình muốn. – GManNickG

+0

@aaa: Điều đó sẽ không hoạt động. –

0

Tôi nghĩ vấn đề là bạn cố gắng để chuyên theo giá trị thay vì loại ...

+2

Bạn có thể chuyên về giá trị. Vấn đề là số học trong chuyên môn. – GManNickG

0

Dưới đây là một cái gì đó mà làm việc cho tôi: sử dụng một đối số mặc định cho _2 thay vì cố gắng chuyên.

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

Điều đó có giống như những gì bạn muốn không?

+0

aaa thực sự muốn viết một phiên bản chuyên biệt của mẫu, không chỉ là một đối số mặc định. Dù sao thì, anh ta đã tìm được cách giải quyết tốt với mẹo "bool liên tiếp = (_1 == _2 - 1)": –

1

Bạn cũng có thể di chuyển tình trạng từ mẫu tiểu học vào chuyên môn hóa. Bí quyết là trong khi các thông số không gõ vào tiểu biểu thức không được phép vào không loại lập luận chuyên môn, họ được phép trong lập luận kiểu

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

Đôi khi, người ta cũng sử dụng SFINAE cho việc này. Các truy cập sau đây ::type chỉ có ở đó nếu điều kiện là đúng. Nếu sai, loại đó không có và SFINAE sắp xếp chuyên môn.

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

Với enable_if là nổi tiếng sau mẫu

template<bool C, typename R = void> 
struct enable_if { }; 

template<typename R = void> 
struct enable_if<true, R> { typedef R type; }; 
Các vấn đề liên quan