In Python I can do this:
>>> import itertools
>>> for i, j, in itertools.product(range(3), repeat=2): print i, j
...
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
Is it possible to have an easy-to-read, non-boost version of this in C++?
In Python I can do this:
>>> import itertools
>>> for i, j, in itertools.product(range(3), repeat=2): print i, j
...
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
Is it possible to have an easy-to-read, non-boost version of this in C++?
Looping example (updated):
#include <array>
#include <iostream>
#include <utility>
template<int VRange, int VRepCount, int VValueRIndex = VRepCount> class
t_Looper
{
public: template<typename TAction> static void
process(::std::array<int, VRepCount> & values, TAction && action)
{
for(;;)
{
t_Looper<VRange, VRepCount, VValueRIndex - 1>::process(values, ::std::forward<TAction>(action));
auto & value{values[VRepCount - VValueRIndex]};
if((VRange - 1) != value)
{
++value;
}
else
{
value = 0;
break;
}
}
}
};
template<int VRange, int VRepCount> class
t_Looper<VRange, VRepCount, 0>
{
private: template<int... VIndexes, typename TAction> static void
invoke(::std::integer_sequence<int, VIndexes...>, ::std::array<int, VRepCount> const & values, TAction && action)
{
action(values[VIndexes]...);
}
public: template<typename TAction> static void
process(::std::array<int, VRepCount> & values, TAction && action)
{
invoke(::std::make_integer_sequence<int, VRepCount>(), values, ::std::forward<TAction>(action));
}
};
template<int VRange, int VRepCount, typename TAction> void
multiloop(TAction && action)
{
::std::array<int, VRepCount> values{};
t_Looper<VRange, VRepCount>::process(values, ::std::forward<TAction>(action));
}
int main()
{
multiloop<3, 2>([](int i, int j){::std::cout << i << " " << j << ::std::endl;});
multiloop<3, 4>([](int i, int j, int k, int l){::std::cout << i << " " << j << " " << k << " " << l << ::std::endl;});
return(0);
}
std::array<int, N>
instead of t_IntsTuple<N>
–
Paymar for(;;)
loop probably can be improved as well by removing duplication somehow. –
Goldthread Ranges are not avalible, but range based loops come quite close.
#include <iostream>
int main(){
for (int i:{1,2,3}) { for (int j:{1,2,3}) {std::cout << i << " " << j <<std::endl;}};
}
or if you like to use the same range
#include <iostream>
int main(){
const auto range {1,2,3};
for (int i:range) {for (int j:range) {std::cout << i << " " << j <<std::endl;}};
}
and just for the fun of it with std::for_each
(this one is perhaps hard to read, but it has no hand written loops)
#include <iostream>
#include <algorithm>
int main(){
const auto range {1,2,3};
std::for_each(range.begin(), range.end(), [range](int i) {std::for_each(range.begin(), range.end(), [i](int j) {std::cout << i << " " << j <<std::endl; } ); } );
}
for(;;)
: for(const auto range {1,2,3};std::for_each(...), false;)
although I doubt that counts as "easy to read" –
Paymar Looping example (updated):
#include <array>
#include <iostream>
#include <utility>
template<int VRange, int VRepCount, int VValueRIndex = VRepCount> class
t_Looper
{
public: template<typename TAction> static void
process(::std::array<int, VRepCount> & values, TAction && action)
{
for(;;)
{
t_Looper<VRange, VRepCount, VValueRIndex - 1>::process(values, ::std::forward<TAction>(action));
auto & value{values[VRepCount - VValueRIndex]};
if((VRange - 1) != value)
{
++value;
}
else
{
value = 0;
break;
}
}
}
};
template<int VRange, int VRepCount> class
t_Looper<VRange, VRepCount, 0>
{
private: template<int... VIndexes, typename TAction> static void
invoke(::std::integer_sequence<int, VIndexes...>, ::std::array<int, VRepCount> const & values, TAction && action)
{
action(values[VIndexes]...);
}
public: template<typename TAction> static void
process(::std::array<int, VRepCount> & values, TAction && action)
{
invoke(::std::make_integer_sequence<int, VRepCount>(), values, ::std::forward<TAction>(action));
}
};
template<int VRange, int VRepCount, typename TAction> void
multiloop(TAction && action)
{
::std::array<int, VRepCount> values{};
t_Looper<VRange, VRepCount>::process(values, ::std::forward<TAction>(action));
}
int main()
{
multiloop<3, 2>([](int i, int j){::std::cout << i << " " << j << ::std::endl;});
multiloop<3, 4>([](int i, int j, int k, int l){::std::cout << i << " " << j << " " << k << " " << l << ::std::endl;});
return(0);
}
std::array<int, N>
instead of t_IntsTuple<N>
–
Paymar for(;;)
loop probably can be improved as well by removing duplication somehow. –
Goldthread Is it possible to have an easy-to-read, non-boost version of this in C++?
No.
You cannot do that in pure C++. You would need a library or so.
There is an Extension for ranges that is experimental in C++14, but even with this, I am not sure if could make it.
if you do not mind creating your own ..
dot-dot operator with the help of these two template functions:
template< int First, int Last , int Step = 1>
int ( &dotdot() )[ ( Step + Last - First ) / Step ]
{
static int result[ ( Step + Last - First ) / Step ];
for( int index = First; index <= Last; index += Step ){
result[ ( index - First ) / Step ] = index;
}
return result;
}
template< int Last, int First, int Step = 1 >
int ( &dotdot() )[ ( Step + Last - First ) / Step ]
{
static int result[ ( Step + Last - First ) / Step ];
for( int index = Last; index >= First; index -= Step ){
result[ ( Last - index ) / Step ] = index;
}
return result;
}
then you can:
for( int i : dotdot<0,2>() ) for( int j : dotdot<0,2>() ) std::cout << i << ' ' << j << '\n';
and the output:
0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2
dotdot<'a','z'>()
returns a
to z
dotdot<'z','a',2>()
returns z
to a
and step is 2dotdot<-10,0>()
returns -10
to 0
dotdot<-10,10,3>()
returns -10
to 10
and step is 3Since C++23 you can use the cartesian_product standard library function. Combined with the C++20 range factory, you can easily write an equivalent of your python code like this:
#include <iostream>
#include <ranges>
using std::ranges::views::iota, std::views::cartesian_product;
int main() {
auto range = iota(0, 3);
for (auto const& [i, j] : cartesian_product(range, range))
std::cout << i << ' ' << j << std::endl;
}
© 2022 - 2024 — McMap. All rights reserved.
std::integer_sequence
? – Rattlesnake