2010-04-11 7 views
6

Ich versuche Vorlage die folgende Art und Weise zu spezialisieren:C++ Template untypische Konstruktionen Parameter Arithmetik

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

aber ich Compiler Fehlermeldung erhalten

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

Was tun meine falsch? danke

Ich habe Workaround in Kommentaren. Anscheinend kann ich in der Template-Spezialisierung nicht rechnen. scheint kontraintuitiv zu sein.

Hier ist meine endgültige Lösung in dem Problem zu lösen. Im Grunde benötigt aufeinanderfolgender Index nur eine Multiplikation.

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

etwas größer Bild würde hier helfen. Sie müssen ein bisschen Design ändern, um den gleichen Effekt zu erzielen. Auch die Zeilennummern stehen tendenziell im Weg. :) – GManNickG

+0

@GMan Ich nehme an, ich kann extra Standardargument verwenden, 'bool konsekutiv = _1 == _2 - 1'? – Anycorn

+0

Ich freue mich darauf, dieses beantwortet zu sehen. Es wird mein Verständnis der Sprache verbessern. – Omnifarious

Antwort

4

ich meine Lösung bin Entsendung wird von GMan vorgeschlagen

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

Sie können das statische 'eval' loswerden und einfach den Wert zu einer tatsächlichen statischen Variable machen. Auf diese Weise können Sie auf den Wert als verschachtelten ':: Wert 'zugreifen, anstatt eine Funktion aufzurufen (die zur Laufzeit noch auftritt). –

+0

Abhängig davon, was "Multiplizieren" bewirkt, kann dieser Ausdruck möglicherweise sogar in eine "Enumeration" verschoben werden. (Nach dem Beseitigen des Anrufs natürlich.) – Potatoswatter

1

versuchen, etwas wie folgt aus:

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

Ich versuche Fälle zu spezialisieren, in denen das zweite Argument größer als das erste ist – Anycorn

+0

Dann verliert er den Effekt, den er wollte. – GManNickG

+0

@aaa: Das wird nicht funktionieren. –

0

Ich denke, das Problem ist, dass Ihr nach Wert anstelle der Art zu spezialisiert versuchen ...

+2

Sie können sich spezialisieren nach Wert. Das Problem ist die Arithmetik innerhalb der Spezialisierung. – GManNickG

0

Hier ist etwas, das funktioniert für mich: Verwenden Sie ein Standardargument für _2 statt zu versuchen, zu spezialisieren.

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

Sieht das so aus, wie Sie wollen?

+0

aaa möchte wirklich eine spezialisierte Version der Vorlage schreiben, nicht nur ein Standardargument. Wie auch immer, er fand schon eine nette Abhilfe mit dem "Bool konsekutiv = (_1 == _2 - 1)" Trick :) –

1

Sie auch den Zustand von der primären Vorlage in die Spezialisierung bewegen kann. Der Trick besteht darin, dass, während Nicht-Typ-Parameter in Unterausdrücke in nicht-Typ Spezialisierung nicht erlaubt sind Argumente, sie in Art Argumente sind erlaubt

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

Occassionally, Menschen SFINAE für diesen Einsatz auch. Der folgende Zugriff ::type ist nur vorhanden, wenn die Bedingung wahr ist. Wenn es falsch ist, ist der Typ nicht vorhanden und SFINAE sortiert die Spezialisierung aus.

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

Mit enable_if der folgenden bekannten Vorlage seines

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

template<typename R = void> 
struct enable_if<true, R> { typedef R type; }; 
Verwandte Themen