Ich habe versucht, einen Code für die funktionale Erstellung von Sequenzen zu schreiben. Ich schrieb eine Funktion, range(a, b)
, die ein Objekt zurückgibt, das iteriert werden kann, foreach-style, durch die Zahlen a, a + 1, ..., b - 1. Dann schrieb ich eine andere Funktion, map(f, t)
, die zurückgibt ein anderes iterierbares Objekt, bei dem jedes Element in der Sequenz das Ergebnis des Aufrufs von f
mit dem entsprechenden Element des iterierbaren Objekts t
ist.Warum optimiert gcc diese C++ 11 foreach-Schleife mit meinem benutzerdefinierten Iterator?
Dies funktioniert wie erwartet, wenn ich kompilieren mit -O1
oder niedriger; mit -O2
oder höher, meine foreach loop (in main
an der unterseite) wird komplett weg optimiert und nichts ist gedruckt. Warum passiert das, was habe ich falsch gemacht? Hier ist mein Code:
template<typename T>
struct _range {
T a;
T b;
_range(T a, T b):
a(a),
b(b)
{
}
struct iterator {
T it;
iterator(T it):
it(it)
{
}
bool operator!=(const iterator &other) const
{
return it != other.it;
}
void operator++()
{
++it;
}
T operator*() const
{
return it;
}
};
iterator begin() const
{
return iterator(a);
}
iterator end() const
{
return iterator(b);
}
};
template<typename T>
_range<T> range(const T a, const T b)
{
return _range<T>(a, b);
}
template<typename F, typename T>
struct _map {
const F &f;
const T &t;
_map(const F &f, const T &t):
f(f),
t(t)
{
}
struct iterator {
const F &f;
typename T::iterator it;
iterator(const F &f, typename T::iterator it):
f(f),
it(it)
{
}
bool operator!=(const iterator &other) const
{
return it != other.it;
}
void operator++()
{
++it;
}
int operator*() const
{
return f(*it);
}
};
iterator begin() const
{
return iterator(f, t.begin());
}
iterator end() const
{
return iterator(f, t.end());
}
};
template<typename F, typename T>
_map<F, T> map(const F &f, const T &t)
{
return _map<F, T>(f, t);
}
#include <algorithm>
#include <cstdio>
int main(int argc, char *argv[])
{
for (int i: map([] (int x) { return 3 * x; }, range(-4, 5)))
printf("%d\n", i);
return 0;
}
Vielleicht ein Fehler? Mit Clang ++ funktioniert es sowohl bei den O1- als auch bei den O2-Optimierungsebenen. –
Versuchen Sie, '_map' speichern seine Mitglieder nach Wert anstatt const refs zu speichern. (Ich vermute, dass dein "Entfernungs" -Objekt früher zerstört wird, als du gehofft hast.) – ildjarn
Ich glaube, @ildjarn hat es richtig verstanden: Das Temporäre ist gezwungen zu leben, solange die konstante Referenz, an die es gebunden ist, am Leben ist. Die Referenz, an die es gebunden ist, ist das Argument des Konstruktors von map. Wenn der Konstruktor zurückkehrt, wird der Verweis ungültig und das temporäre Objekt wird gelöscht. –