私は、機能スタイルのシーケンスの作成を行うためのコードを書くことを試みていました。私は1つの関数range(a, b)
を書いています。これはforeachスタイルで反復してa、a + 1、...、b-1の数値を返すオブジェクトを返します。次に別の関数map(f, t)
を返します。シーケンス中の各要素は、反復可能オブジェクトt
の対応する要素を持つf
を呼び出した結果である別の反復可能オブジェクトです。gccは私のカスタムイテレータを使ってこのC++ 11 foreachループを最適化するのはなぜですか?
これは、-O1
以下を使用してコンパイルすると正常に動作します。 -O2
以上では、私のforeachループ(最下部のmain
)が完全に最適化され、何も印刷されません。なぜこれが起こるのですか、私は何が間違っていますか?既存のコメントをまとめる
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;
}
バグかもしれませんか? Clang ++では、O1とO2の両方の最適化レベルでうまく動作します。 –
'_map'がconst refを格納するのではなく、値でメンバーを格納するようにしてください。 (あなたの 'range'オブジェクトがあなたが望んでいたよりも早く破壊されていると思われます。) – ildjarn
@ildjarnは正しいと思います:一時的なものは、それがバインドされている定数参照が生きている限り、バインドされている参照は 'map'のコンストラクタの引数です。コンストラクタが返ってくると、参照が範囲外になり、一時的なものが破棄されます。 –