Dizilerin fonksiyonel tarzı oluşturulmasında bazı kodlar yazmaya çalışıyordum. Bir işlev, range(a, b)
yazdım, bir nesne döndürdüğünüz bir nesneyi döndürür, foreach stili, a, a + 1, ..., b - 1 sayıları boyunca ilerler. Sonra başka bir işlev yazdım, map(f, t)
Sekanstaki her bir elemanın, f
numaralı telefonun yinelenen nesnesinin t
karşılık gelen elemanı ile aranmasının bir başka yinelenen nesnesi.Neden gcc bu özel yineleyici kullanarak bu C++ 11 foreach döngüsünü optimize eder?
-O1
veya daha düşük bir sürümü kullanarak derlerseniz bu beklendiği gibi çalışır; -O2
veya üstü ile, foreach döngüsüm (altta main
'da) tamamen en iyi duruma getirilir ve hiçbir şey yazdırılmaz. Bu neden oluyor, neyi yanlış yaptım? mevcut yorumların Özetle
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;
}
Belki bir hata? Clang ++ ile, hem O1 hem de O2 optimizasyon seviyelerinde çalışır. –
'_map' üyelerini const refs depolamak yerine değerlerine göre depolamayı deneyin. ('Range' nesnesinin umduğundan daha önce yok edildiğinden şüpheleniyorum.) – ildjarn
inanıyorum inanıyorum: @ildjarn haklıydı: geçici olarak bağlı olduğu sabit referans olduğu sürece yaşamak zorunda kalıyor. bağlandığı referans, 'haritanın kurucusunun argümanıdır. Kurucu geri döndüğünde, referans kapsam dışı kalır ve geçici olarak yok olur. –