Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Unglaublich, dass das funktioniert:

2 views
Skip to first unread message

Bonita Montero

unread,
Dec 17, 2023, 9:28:30 AM12/17/23
to
Am 17.12.2023 um 14:27 schrieb Bonita Montero:
> int main( int argc, char ** )
> {
>     switch( argc )
>     {
>         for( ; ; )
>         {
>         case 1:;
>         }
>     }
> }
>
> Hab ich gerade in einem alten C-Programm von 1999 gesehen, dass
> das jemand gemacht hat. Für manche mag das schlecht wirken weil
> es unüblich ist.

Ach, sollte eigentlich hier hin.

Peter J. Holzer

unread,
Dec 17, 2023, 9:46:41 AM12/17/23
to
On 2023-12-17 14:28, Bonita Montero <Bonita....@gmail.com> wrote:
> Am 17.12.2023 um 14:27 schrieb Bonita Montero:
>> int main( int argc, char ** )
>> {
>>     switch( argc )
>>     {
>>         for( ; ; )
>>         {
>>         case 1:;
>>         }
>>     }
>> }

Das Fragment hier ist zu kurz, als dass ich hier den Sinn erkennen
könnte, aber ja, das geht, und es gibt - selten aber doch -
Anwendungsfälle dafür.


>> Hab ich gerade in einem alten C-Programm von 1999 gesehen, dass
>> das jemand gemacht hat. Für manche mag das schlecht wirken weil
>> es unüblich ist.
>
> Ach, sollte eigentlich hier hin.
>

Siehe auch "Duff's Device".

Bonita Montero

unread,
Dec 18, 2023, 12:39:53 PM12/18/23
to
Am 17.12.2023 um 15:46 schrieb Peter J. Holzer:

> Siehe auch "Duff's Device".

Loop-Unrolling geht ohne manuelle Replizierung der einzelnen Statements
in einer Sprache die das erlaubt. Das ist mein unroll.h:

#pragma once
#include <utility>
#include <concepts>
#include <iterator>

#if defined(_MSC_VER)
#define UNROLL_FORCEINLINE __forceinline inline
#elif defined(__GNUC__) || defined(__clang__)
#define UNROLL_FORCEINLINE __attribute__((always_inline)) inline
#else
#define UNROLL_FORCEINLINE inline
#endif

template<size_t N, typename Fn>
requires requires( Fn fn ) { { fn.template operator ()<(size_t)N - 1>()
} -> std::convertible_to<bool>; }
UNROLL_FORCEINLINE bool unroll( Fn fn )
{
auto unroll_n = [&]<size_t ... Indices>( std::index_sequence<Indices
...> ) -> bool
{
return (fn.template operator ()<Indices>() && ...);
};
return unroll_n( std::make_index_sequence<N>() );
}

template<size_t N, typename Fn>
requires requires( Fn fn ) { { fn.template operator ()<(size_t)N - 1>()
} -> std::same_as<void>; }
UNROLL_FORCEINLINE void unroll( Fn fn )
{
unroll<N>( [&]<size_t I>() { fn.template operator ()<I>(); return true;
} );
}

template<std::size_t N, std::random_access_iterator RandomIt, typename Fn>
requires requires( Fn fn, std::iter_common_reference_t<RandomIt> elem )
{ { fn.template operator()<(size_t)-1>( elem ) } -> std::same_as<bool>; }
UNROLL_FORCEINLINE RandomIt unroll_for_each( RandomIt begin, RandomIt
end, Fn fn )
{
if constexpr( N > 1 )
for( ; end - begin >= N && unroll<N>( [&]<size_t I>() { return
fn.template operator ()<I>( begin[I] ); } ); begin += N );
for( ; begin != end && fn.template operator ()<(size_t)-1>( *begin );
++begin );
return begin;
}

template<std::size_t N, std::random_access_iterator RandomIt, typename Fn>
requires requires( Fn fn, std::iter_common_reference_t<RandomIt> elem )
{ { fn.template operator()<(size_t)-1>( elem ) } -> std::same_as<void>; }
UNROLL_FORCEINLINE RandomIt unroll_for_each( RandomIt begin, RandomIt
end, Fn fn )
{
return unroll_for_each<N>( begin, end,
[&]<size_t I>( std::iter_common_reference_t<RandomIt> &value ) {
fn.template operator ()<I>( value ); return true; } );
}

Damit macht man dann sowas wie:

vector<int> vi( ... );
..
int sum = 0;
unroll_for_each<5>( vi.begin(), vi.end(),
[&]<size_t I>( int elem ) { sum += elem; } );
0 new messages