5
// if I know that in_x will never be bigger than Max
template <unsigned Max>
void foo(unsigned in_x)
{
    unsigned cap = Max;

    // I can tell the compiler this loop will never run more than log(Max) times
    for (; cap != 0 && in_x != 0; cap >>= 1, in_x >>= 1)
    {
    }
}

上記のコードに示されているように、私の推測では、

for(; in_x!= 0; in_x >> = 1)

コンパイラはループを展開しません。可能な最大のin_xについて確信が持てないためです。

私が正しいか間違っているか、そしてそのようなことに対処するためのより良い方法があるかどうかを知りたいです。


あるいは、問題は、コンパイラに実行時の値の範囲を指示するコードを記述できるかのように一般化でき、そのようなコードは必ずしも実行時のバイナリにコンパイルされるとは限りません。


本当に、コンパイラXDと戦う

// with MSC
// if no __forceinline here, unrolling is ok, but the function will not be inlined
// if I add __forceinline here, lol, the entire loop is unrolled (or should I say the tree is expanded)...
// compiler freezes when Max is something like 1024
template <int Max>
__forceinline void find(int **in_a, int in_size, int in_key)
{
    if (in_size == 0)
    {
        return;
    }

    if (Max == 0)
    {
        return;
    }

    {
        int m = in_size / 2;

        if ((*in_a)[m] >= in_key)
        {
            find<Max / 2>(in_a, m, in_key);
        }
        else
        {
            *in_a = *in_a + m + 1;

            find<Max - Max / 2 - 1>(in_a, in_size - (m + 1), in_key);
        }
    }
}
4

1 に答える 1

3

この種の動作を実現する適切な方法は、TMPを使用して自分でループを展開することです。これでも、大規模なインライン化(​​許可されていません)についてはコンパイラの協力に依存することになります。次のコードを見て、役立つかどうかを確認してください。

template <unsigned char MaxRec>
inline void foo(unsigned in_x)
{
    if (MaxRec == 0) // will be eliminated at compile time
        return; // tells the compiler to stop the pseudo recursion

    if (in_x == 0) {
        // TODO : end recursion;
        return;
    };

    // TODO: Process for iteration rec

    // Note: NOT recursion, the compiler would not be able to inline
    foo<MaxRec-1>(in_x >> 1);
}

// Usage:
foo<5>(in_x); // doubt the compiler will inline 32 times, but you can try.
于 2012-03-03T13:06:14.520 に答える