Es ist gut ganze Zahlen ohne Vorzeichen definiert zu verwenden (und size_t
ist unsigned) auf diese Weise, mit Wraparound: das Verhalten von der Norm gewährleistet ist, im Gegensatz zu mit signierten ganzen Zahlen, wo es ist nicht durch den Standard garantiert.
Es ist jedoch unnötig clever.
Um Probleme aufgrund von impliziten Wrapping-Aktionen zu vermeiden, verwenden Sie vorzeichenlose Ganzzahlen für Bitebenen, verwenden Sie vorzeichenbehaftete Ganzzahlen für Zahlen. Wo Sie eine vorzeichenbehaftete Ganzzahl benötigen, die size_t
entspricht, gibt es ptrdiff_t
für Sie. Definieren Sie eine n_items
-Funktion mit einem vorzeichenbehafteten Ergebnis, z.
using Size = ptrdiff_t;
template< class Container >
auto n_items(Container const& c)
-> Size
{ return end(c) - begin(c); }
und Sie sind bereit zu gehen, keine dummen Warnungen vom Compiler.
Statt des zu klug gegebenen Code
vector<int> v { 1,2,3,4,5 };
bool rev = true;
size_t start, end, di;
if (rev) {
start = v.size()-1;
end = -1;
di = -1;
}
else {
start = 0;
end = v.size();
di = 1;
}
for (auto i=start; i!=end; i+=di) {
cout << v[i] << endl;
tun z.B.
const vector<int> v { 1,2,3,4,5 };
const bool reverse = true; // whatever
for(int i = 0; i < n_items(v); ++i)
{
const int j = (reverse? n_items(v) - i - 1 : i);
cout << v[j] << endl;
}
Der Standard definiert 'std :: string :: npos' als' static const size_type npos = -1; 'was im Grunde ein ähnlicher Trick ist. Um pedantisch zu sein, könnten Sie bevorzugen: 'std :: vector :: size_type start, end, di;'. –
Galik
@Galic: Ich verstehe nicht, was die Pedanterie (wie du es nennst) erreicht, welchen Vorteil sie hat. Wenn ein Betreuer seinen Weg verlässt, um Dinge zu brechen, indem er 'std :: vector' mit einem Zuweiser instanziiert eine alberne Größe, alles, was die Pedanterie tut, erhöht die Chance, dass es ihr gelingt, Dinge zu verderben. Wie ich es sehe. –
@ Cheersandthth.-Alf Nun, du hast wahrscheinlich recht. Soweit ich sagen kann, obwohl der Standard besagt, dass 'std :: vector :: size_type' muss unsigned sein, aber ich denke, es kann eine andere Größe sein als' std :: size_t'. Obwohl ich mir vorstelle, dass die meisten Implementierungen "size_type" genauso machen wie "size_t". –
Galik