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

What is the good of new way of coding?

25 views
Skip to first unread message

wij

unread,
Sep 17, 2022, 8:47:06 AM9/17/22
to
I did not update my C++ understanding (probable since C++11) to find out I
cannot understand what the codes are about !!!

--- frorm https://groups.google.com/g/comp.lang.c++/c/2ebc6ifoPr4
#include <iostream>
#include <utility>

using namespace std;

int main()
{
auto pow = []<unsigned P>( double b, integral_constant<unsigned, P> )
-> double
{
auto unroll = [&]<size_t ... Indices>( index_sequence<Indices ...> )
-> double
{
return ((Indices, b) * ...);
};
if constexpr( P )
return unroll( make_index_sequence<P>() );
else
return b;
};
cout << pow( 2.0, integral_constant<unsigned, 10'000>() ) << endl;
}
------

Question1: What would the code look like if using C++2006 for the above 'program'?
Question2: What is the good of such way of coding?

Bonita Montero

unread,
Sep 17, 2022, 9:03:23 AM9/17/22
to
It's not possible to write that before C++20.

Bonita Montero

unread,
Sep 17, 2022, 9:23:23 AM9/17/22
to
The code in my initial posting just was some kind of compiler killer
code since the index-sequence resulted in a row of 10,000 size_t's.
But you could write that all smarter like that:

#include <iostream>
#include <utility>

using namespace std;

int main()
{
auto pow = []<unsigned P>( double b, integral_constant<unsigned, P> )
-> double
{
if constexpr( P )
{
double r = 1.0;
[&]<size_t ... Indices>( index_sequence<Indices ...> ) constexpr
{
((r *= P >> Indices & 1 ? b : 1.0, b *= b), ...);
}( make_index_sequence<sizeof(unsigned) * 8>() );
return r;
}
else
return b;
};
cout << pow( 2.0, integral_constant<unsigned, 10>() ) << endl;
}

Bonita Montero

unread,
Sep 17, 2022, 9:38:45 AM9/17/22
to
Am 17.09.2022 um 15:23 schrieb Bonita Montero:
> The code in my initial posting just was some kind of compiler killer
> code since the index-sequence resulted in a row of 10,000 size_t's.
> But you could write that all smarter like that:
>
> #include <iostream>
> #include <utility>
>
> using namespace std;
>
> int main()
> {
>     auto pow = []<unsigned P>( double b, integral_constant<unsigned, P>
> ) -> double
>     {
>         if constexpr( P )
>         {
>             double r = 1.0;
>             [&]<size_t ... Indices>( index_sequence<Indices ...> )
> constexpr
>             {
>                 ((r *= P >> Indices & 1 ? b : 1.0, b *= b), ...);
>             }( make_index_sequence<sizeof(unsigned) * 8>() );
>             return r;
>         }
>         else
>             return b;
return 1.0;

Andreas Kempe

unread,
Sep 17, 2022, 10:37:23 AM9/17/22
to
As was pointed out, you can't really write that code without variadic
templates. What is does at it's core, if I'm not mistaken, is expanding

((Indices, b) * ...)

to

(0, 2.0) * (1, 2.0) * (2, 2.0) * ... * (9999, 2.0)

using modern template magic. The comma operator makes the first index
value disappear and we get

2.0 * 2.0 * 2.0 * ...

10000 times. Writing something that solves the same problem with a loop
could be

double result = 1;
for (size_t i = 0; i < 10000; i++)
result *= (i, 2.0);

> Question2: What is the good of such way of coding?

I personally don't know. I have still to see an example of a variadic
template application that I think makes sense and makes the code more
readable.

Bonita Montero

unread,
Sep 17, 2022, 10:40:47 AM9/17/22
to
container.emplace*( ... ) is a good example.


Mut...@dastardlyhq.com

unread,
Sep 17, 2022, 10:50:55 AM9/17/22
to
Really? So it outputs some special assembler reserved for C++20 does it?

Mut...@dastardlyhq.com

unread,
Sep 17, 2022, 10:52:20 AM9/17/22
to
Showing off. He's constantly posting convoluted code to this group desperate
for someone to say "Wow, impressive, you're so clever!"

Bonita Montero

unread,
Sep 17, 2022, 11:31:16 AM9/17/22
to
No, you can't unroll variable.


Bonita Montero

unread,
Sep 17, 2022, 11:32:00 AM9/17/22
to
I don't wanted to show sth. impressive but I wanted to make
others to compile that.


Mut...@dastardlyhq.com

unread,
Sep 17, 2022, 12:00:03 PM9/17/22
to
On Sat, 17 Sep 2022 17:31:19 +0200
I'm pretty sure the same functionality could be achieved in older C++ or
even C albeit with more lines of code.

Bonita Montero

unread,
Sep 17, 2022, 12:03:33 PM9/17/22
to
Show me.


Mut...@dastardlyhq.com

unread,
Sep 17, 2022, 12:14:06 PM9/17/22
to
On Sat, 17 Sep 2022 18:03:37 +0200
I don't have a c++ 20 compiler so I can't see what it does and I have better
things to do on a saturday than run it in my head.

Bonita Montero

unread,
Sep 17, 2022, 12:34:41 PM9/17/22
to
Without C++20 you would have to unroll the fold expressions
N times, in this case 10.000 times. Have fun !



Alf P. Steinbach

unread,
Sep 17, 2022, 1:55:42 PM9/17/22
to
The Boost preprocessor library comes to mind.


- Alf



Chris M. Thomasson

unread,
Sep 17, 2022, 3:03:35 PM9/17/22
to
Iirc Boost preprocessor is based on the Chaos preprocessor codebase,
right? Anyway, check out this loop unrolling in C for a HMAC lib:

https://github.com/ogay/hmac/blob/master/sha2.c

Macros indeed. Search the code for UNROLL_LOOPS :^)

Andreas Kempe

unread,
Sep 17, 2022, 4:52:22 PM9/17/22
to
Ah, I didn't really consider emplace.

Even though I use it myself and do see the advantage of constructing
elements in-place in a container to avoid a move, I'm not too sure I
really find it an improvement when it comes to readability.
Personally, I find vector.push_back(MyType(arg1, arg2)) clearer when
reading code. With emplace, I have to jump to the container
declaration to find what type is being put into it.

As for the implementation of emplace itself, I can of course not say
much regarding variadic templates affecting the readability since I
see no way of implementing the function without them.

Mr Flibble

unread,
Sep 17, 2022, 5:18:51 PM9/17/22
to
Not all types can efficiently move (i.e. move is a copy) or they are
not even copyable ergo the rationale for emplace.

/Flibble

Mr Flibble

unread,
Sep 17, 2022, 5:21:39 PM9/17/22
to
To be fair I was talking about containers in general, as far as vector
is concerned the value_type does need to be at least copyable.

/Flibble

Andreas Kempe

unread,
Sep 17, 2022, 5:31:42 PM9/17/22
to
Yes. I've written such types myself where I chose an std::list with
emplace to avoid having to make the type moveable or copyable. I
fully understand the need of emplace and that variadic templates are
the way to do it with the current feature set of C++. It was purely
from a readability viewpoint I dislike it.

Same thing goes for auto, really. I don't like it because I think it
lessens readability, but there are cases, like overly long iterator
types and templates/lambdas with complex or unknown return types where
it is definitely needed.

// Andreas Kempe

Bonita Montero

unread,
Sep 18, 2022, 10:21:18 AM9/18/22
to
Am 17.09.2022 um 21:03 schrieb Chris M. Thomasson:

> Iirc Boost preprocessor is based on the Chaos preprocessor codebase,
> right? Anyway, check out this loop unrolling in C for a HMAC lib:
> https://github.com/ogay/hmac/blob/master/sha2.c
> Macros indeed. Search the code for UNROLL_LOOPS :^)

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

template<size_t N, bool Unroll, typename Fn>
requires (N >= 1) && requires( Fn fn ) { { fn() } -> std::same_as<void>; }
inline
void unroll( Fn fn )
{
if constexpr( Unroll )
{
auto unroll_n = [&]<size_t ... Indices>( std::index_sequence<Indices
..> )
{
return ((Indices, fn()), ...);
};
unroll_n( std::make_index_sequence<N>() );
}
else
for( size_t i = 0; i != N; fn(), ++i );
}

template<size_t N, bool Unroll, typename Fn>
requires (N >= 1) && requires( Fn fn, size_t i ) { { fn( i ) } ->
std::convertible_to<bool>; }
inline
bool unroll( Fn fn )
{
if constexpr( Unroll )
{
auto unroll_n = [&]<size_t ... Indices>( std::index_sequence<Indices
..> ) -> bool
{
return (fn( Indices ) && ...);
};
return unroll_n( std::make_index_sequence<N>() );
}
else
{
for( size_t i = 0; i != N; )
if( !fn( i++ ) )
return false;
return true;
}
}

template<size_t N, typename Fn>
requires (N >= 1) && requires( Fn fn ) { { fn.template operator
()<(size_t)N - 1>() } -> std::convertible_to<bool>; }
inline
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, bool Unroll, typename Fn>
requires (N >= 1) && requires( Fn fn ) { { fn() } ->
std::convertible_to<bool>; }
inline
bool unroll( Fn fn )
{
if constexpr( Unroll )
{
auto unroll_n = [&]<size_t ... Indices>( std::index_sequence<Indices
..> ) -> bool
{
return ((Indices, fn()) && ...);
};
return unroll_n( std::make_index_sequence<N>() );
}
else
{
for( size_t i = 0; i != N; ++i )
if( !fn() )
return false;
return true;
}
}

template<std::size_t N, typename RandomIt, typename UnaryFunction>
requires std::random_access_iterator<RandomIt>
&& requires( UnaryFunction fn, std::iter_value_t<RandomIt> elem ) { {
fn( elem ) }; }
inline
RandomIt unroll_for_each( RandomIt begin, RandomIt end, UnaryFunction fn )
{
RandomIt &it = begin;
if constexpr( N > 1 )
for( ; it + N <= end; it += N )
unroll<N>( [&]<std::size_t I>() { fn( it[I] ); } );
for( ; it < end; ++it )
fn( *begin );
return it;
}

Mut...@dastardlyhq.com

unread,
Sep 19, 2022, 4:31:05 AM9/19/22
to
On Sat, 17 Sep 2022 18:34:44 +0200
Bonita Montero <Bonita....@gmail.com> wrote:
>Am 17.09.2022 um 18:13 schrieb Mut...@dastardlyhq.com:
>>>>> No, you can't unroll variable.
>>>>
>>>> I'm pretty sure the same functionality could be achieved in older C++ or
>>>> even C albeit with more lines of code.
>>>>
>>>
>>> Show me.
>>>
>>
>> I don't have a c++ 20 compiler so I can't see what it does and I have better
>> things to do on a saturday than run it in my head.
>>
>
>Without C++20 you would have to unroll the fold expressions
>N times, in this case 10.000 times. Have fun !

Has c++20 just invented recursion then?

I've never seen anything in C++ that couldn't be done in C albeit with much
more - often messy - code. I doubt that has changed.

Bonita Montero

unread,
Sep 19, 2022, 4:37:03 AM9/19/22
to
Am 19.09.2022 um 10:30 schrieb Mut...@dastardlyhq.com:
> On Sat, 17 Sep 2022 18:34:44 +0200
> Bonita Montero <Bonita....@gmail.com> wrote:
>> Am 17.09.2022 um 18:13 schrieb Mut...@dastardlyhq.com:
>>>>>> No, you can't unroll variable.
>>>>>
>>>>> I'm pretty sure the same functionality could be achieved in older C++ or
>>>>> even C albeit with more lines of code.
>>>>>
>>>>
>>>> Show me.
>>>>
>>>
>>> I don't have a c++ 20 compiler so I can't see what it does and I have better
>>> things to do on a saturday than run it in my head.
>>>
>>
>> Without C++20 you would have to unroll the fold expressions
>> N times, in this case 10.000 times. Have fun !
>
> Has c++20 just invented recursion then?

No, C++17 has added fold expressions and C++20 has added templated lambdas.



Mut...@dastardlyhq.com

unread,
Sep 19, 2022, 4:54:47 AM9/19/22
to
On Mon, 19 Sep 2022 10:37:08 +0200
Bonita Montero <Bonita....@gmail.com> wrote:
>Am 19.09.2022 um 10:30 schrieb Mut...@dastardlyhq.com:
>> On Sat, 17 Sep 2022 18:34:44 +0200
>> Bonita Montero <Bonita....@gmail.com> wrote:
>>> Am 17.09.2022 um 18:13 schrieb Mut...@dastardlyhq.com:
>>>>>>> No, you can't unroll variable.
>>>>>>
>>>>>> I'm pretty sure the same functionality could be achieved in older C++ or
>>>>>> even C albeit with more lines of code.
>>>>>>
>>>>>
>>>>> Show me.
>>>>>
>>>>
>>>> I don't have a c++ 20 compiler so I can't see what it does and I have
>better
>>>> things to do on a saturday than run it in my head.
>>>>
>>>
>>> Without C++20 you would have to unroll the fold expressions
>>> N times, in this case 10.000 times. Have fun !
>>
>> Has c++20 just invented recursion then?
>
>No, C++17 has added fold expressions and C++20 has added templated lambdas.

Useful no doubt, but yet more syntactic noise in the language. Reminds me of
the old irish joke of "If you want to get there you really don't want to
start from here".

Bonita Montero

unread,
Sep 19, 2022, 5:13:13 AM9/19/22
to
If you use functional and generic programming there's no alternative
to templated lambdas for me. If you use variadic templates there's
no alternative to fold expressions; otherwise you would have to use
this tail-recursion hacks.
C++20 has become much straighter.

0 new messages