How do you write the alternate for "ranged based for" that is a part of c++11 in older versions of C++
for (boost::property_tree::ptree::iterator iter = root.begin() ; iter != root.end() ; iter++)
{
for (auto& array_element : iter->second)
{
//Some Lines
}
}
Related
I'm learning Rust right now and I'm using this simple Sieve of Erathostenes implementation:
fn get_primes(known_primes: &Vec<i64>, start: i64, stop: i64) -> Vec<i64> {
let mut new_primes = Vec::new();
for number in start..stop {
let mut is_prime = true;
let limit = (number as f64).sqrt() as i64;
for prime in known_primes {
if number % prime == 0 {
is_prime = false;
break;
}
if *prime > limit {
break;
}
}
if is_prime {
new_primes.push(number);
}
}
return new_primes;
}
I'm comparing it to virtually the same code (modulo syntax) in Python (with numba), C#, and C++ (gcc/clang). All of them are about 3x faster than this implementation on my machine.
I am compiling in release mode. To be exact, I've added this to my Cargo.toml, which seems to have the same effect:
[profile.dev]
opt-level = 3
I've also checked the toolchain, there is a slight (15% or so) difference between MSVC and GNU, but nothing that would explain this gap.
Am I getting something wrong here? Am I making a copy somewhere?
Is this code equivalent to the following C++ code?
vector<int> getPrimes(vector<int> &knownPrimes, int start, int stop) {
vector<int> newPrimes;
for (int number = start; number < stop; number += 1) {
bool isPrime = true;
int limit = (int)sqrt(number);
for (auto& prime : knownPrimes) {
if (number % prime == 0) {
isPrime = false;
break;
}
if (prime > limit)
break;
}
if (isPrime) {
newPrimes.push_back(number);
}
}
return newPrimes;
}
The size of a C++ int depends on target architecture, compiler options etc.. In the Rust code, you explicitly state a 64-bit integer. You may be comparing code using different underlying type sizes.
Is it possible to loop over sub range using range based for loop ?
std::vector <std::string> inputs={"1","abaaaa","abc","cda"};
for (auto &it : new_vector(inputs.begin()+1, inputs.end()))
{
// …
}
You could use Boost's iterator_range:
for (auto &it : boost::make_iterator_range(inputs.begin()+1, inputs.end()))
{
cout << it << endl;
}
demo
Alternatively you could write your own wrapper.
Unfortunately, there is no such thing in the C++ standard library. However, you can define your own wrapper like this (requires at least C++ 11 - which should not be problem in 2021):
template<typename Iter>
struct range
{
Iter b, e;
Iter begin() const { return b; }
Iter end() const { return e; }
};
template<typename T>
auto slice(const T& c, std::size_t from, std::size_t to = -1) -> range<decltype(c.begin())>
{
to = (to > c.size() ? c.size() : to);
return range<decltype(c.begin())>{c.begin() + from, c.begin() + to};
}
And then you can use it:
std::vector<int> items(100);
// Iterates from 4th to 49th item
for (auto x: slice(items, 4, 50))
{
}
// Iterates from 15th to the last item
for (auto x: slice(items, 15))
{
}
tl;dr
Long story short, you #include <range/v3/view/subrange.hpp> and change your new_vector to ranges::subrange. And that's it. Demo on Compiler Explorer.
So
Given the name you imagine for this function, new_vector, maybe you think you need the entity on the right of : to be a std::vector or at least some type of container.
If that's the case, then change your mind, it's not needed. All that : wants from its "right hand side" is that it have begin and end defined on them, member or non member. For instance, this compiles and runs just fine:
struct A {};
int* begin(A);
int* end(A);
struct B {
int* begin();
int* end();
};
int main()
{
for (auto it : A{}) {}
for (auto it : B{}) {}
}
I noticed while doing some F# experiments that if write my own reduce function for Array that it performs much better than the built in reduce. For example:
type Array with
static member inline fastReduce f (values : 'T[]) =
let mutable result = Unchecked.defaultof<'T>
for i in 0 .. values.Length-1 do
result <- f result values.[i]
result
This seems to behave identically to the built in Array.reduce but is ~2x faster for simple f
Is the built in one more flexible in some way?
By looking at the generated IL code it's easier to understand what's happening.
Using the built-in Array.reduce:
let reducer (vs : int []) : int = Array.reduce (+) vs
Gives the following equivalent C# (reverse engineered from the IL code using ILSpy)
public static int reducer(int[] vs)
{
return ArrayModule.Reduce<int>(new Program.BuiltIn.reducer#31(), vs);
}
Array.reduce looks like this:
public static T Reduce<T>(FSharpFunc<T, FSharpFunc<T, T>> reduction, T[] array)
{
if (array == null)
{
throw new ArgumentNullException("array");
}
int num = array.Length;
if (num == 0)
{
throw new ArgumentException(LanguagePrimitives.ErrorStrings.InputArrayEmptyString, "array");
}
OptimizedClosures.FSharpFunc<T, T, T> fSharpFunc = OptimizedClosures.FSharpFunc<T, T, T>.Adapt(reduction);
T t = array[0];
int num2 = 1;
int num3 = num - 1;
if (num3 >= num2)
{
do
{
t = fSharpFunc.Invoke(t, array[num2]);
num2++;
}
while (num2 != num3 + 1);
}
return t;
}
Notice that it invoking the reducer function f is a virtual call which typically the JIT:er struggles to inline.
Compare to your fastReduce function:
let reducer (vs : int []) : int = Array.fastReduce (+) vs
The reverse-engineered C# code:
public static int reducer(int[] vs)
{
int num = 0;
for (int i = 0; i < vs.Length; i++)
{
num += vs[i];
}
return num;
}
A lot more efficient as the virtual call is now gone. It seems that in this case F# inlines both the code for fastReduce as well as (+).
There's some kind of cut-off in F# as more complex reducer functions won't be inlined. I am unsure on the exact details.
Hope this helps
A side-note; Unchecked.defaultOf returns null values for class types in .NET such as string. I prefer LanguagePrimitives.GenericZero.
PS. A common trick for the real performance hungry is to loop towards 0. In F# that doesn't work for for-expressions because of a slight performance bug in how for-expressions are generated. In those case you can try to implement the loop using tail-recursion.
In c++ I can add a reference to a value type, for example :
int a = 12;
int &b = a;
a--;
cout << "a = " << a << ", b = " << b << endl;
Will give :
a = 11, b = 11
Is there a way to do the same in vala without using pointers ?
Is there a way to do the same in vala
Yes.
without using pointers ?
No.
If, however, you are passing them to a function, you can use a ref parameter:
void decrement (ref value) {
value--;
}
void do_stuff () {
int a = 12;
decrement (ref a);
assert (a == 11);
}
How to execute the body of the loop for every member of some type? I know I could repeat the body of the loop for the maxval after the loop, but it would be duplicating code which is bad. I also could make a function out of the body but it looks wrong to me too because functions should be small and simple and the body of the loop is huge.
const auto minval = std::numeric_limits<T>::min();
const auto maxval = std::numeric_limits<T>::max();
for (auto i = minval; i < maxval; ++i) {
// huge body of the loop
}
It is as simple as stopping after you process the last item:
auto i = minval;
while(1) {
// do all the work for `i`
if (i == maxval) break;
++i;
}
One can also move the increment to the top of the loop, provided it is skipped on the first pass:
i = minval;
switch (1) {
case 0:
do {
++i;
case 1:
// processing for `i`
} while (i != maxval);
}
The latter version translates to efficient machine code a little more directly, as each loop iteration has only a single conditional branch, and there is a single unconditional branch, while in the first there is a conditional branch plus an unconditional branch which both repeat every iteration.
Neither version increments the ultimate value, which might be undefined behavior.
You have to maintain a bit of additional state to indicate whether you've seen the last value or not. Here's a simple example that could be moved to a more idiomatic iterator style without too much work:
#include <iostream>
#include <limits>
using namespace std;
template <typename T>
class allvalues
{
public:
allvalues() = default;
T next()
{
if (done) throw std::runtime_error("Attempt to go beyond end of range");
T v = val;
done = v == std::numeric_limits<T>::max();
if (!done) ++val;
return v;
}
bool isDone() { return done; }
private:
T val = std::numeric_limits<T>::min();
bool done = false;
};
int main() {
allvalues<char> range;
while (!range.isDone())
{
std::cout << "Value = " << (int)range.next() << std::endl;
}
allvalues<unsigned char> urange;
while (!urange.isDone())
{
std::cout << "Value = " << (unsigned int)urange.next() << std::endl;
}
std::cout << "That's it!" << std::endl;
}