Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force all && to be executed?

Consider the following variadic function

template <typename Type, typename... Types>
bool f(Type& arg, Types&... args)
{
    return f(arg) && f(args...);
}

template <typename Type>
bool f(Type& arg)
{
    // Do something
} 

If one level of recursion is false, then I suspect that the following will not be executed. Is there a trick to force the recursion on all arguments even if one of them returns false ?

like image 895
Vincent Avatar asked Mar 23 '13 15:03

Vincent


People also ask

What do you mean by force?

In Physics, force is defined as: The push or pull on an object with mass causes it to change its velocity. Force is an external agent capable of changing a body's state of rest or motion. It has a magnitude and a direction.

Who are the 9 DLC characters in Jump Force?

Nine more characters for Jump ForceSeto Kaiba from Yu-Gi-Oh! All Might from My Hero Academia. Hunter x Hunter Biscuit Krueger. Toushirou Hitsugaya from Bleach.

What anime does Jump Force have?

Bandai Namco is pulling Jump Force, the anime crossover fighting game that features characters from Dragon Ball, Naruto, One Piece, JoJo's Bizarre Adventure, and other series, from digital stores on Feb. 7, 2022.


3 Answers

This shouldn't be too hard:

template <typename Type, typename... Types>
bool f(Type& arg, Types&... args)
{
    bool b1 = f(arg);
    bool b2 = f(args...);
    return b1 && b2;
}
like image 98
Andy Prowl Avatar answered Sep 23 '22 23:09

Andy Prowl


As the debate has evolved in a comparison of the AndyProwl and Alon solution, I've benchmarked the both solution, and the result ... depends of the number of arguments.

Compiling with:

g++-4.7 -std=c++11 -Wall -Wextra -O3 main.cpp -o main -D_FIRST

benchmarks the AndyProwl solution and compiling with :

g++-4.7 -std=c++11 -Wall -Wextra -O3 main.cpp -o main -D_SECOND

benchmarks the Alon solution.

Here is the program of the benchmark for 10 arguments.

#include <iostream>
#include <chrono>

// Function 1 : with &&
template <typename Type>
inline bool f1(const Type& arg)
{
   return arg;
}
template <typename Type, typename... Types>
inline bool f1(const Type& arg, const Types&... args)
{
    bool arg1 = f1(arg);
    bool arg2 = f1(args...);
    return arg1 && arg2;
}

// Function 2 : with &
template <typename Type>
inline bool f2(const Type& arg)
{
   return arg;
}
template <typename Type, typename... Types>
inline bool f2(const Type& arg, const Types&... args)
{
    return f2(arg) & f2(args...);
}

// Benchmark
int main(int argc, char* argv[])
{
    // Variables
    static const unsigned long long int primes[10] = {11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
    static const unsigned long long int nbenchs = 50;
    static const unsigned long long int ntests = 10000000;
    unsigned long long int sum = 0;
    double result = 0;
    double mean = 0;
    std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now();

    // Loop of benchmarks
    for (unsigned long long int ibench = 0; ibench < nbenchs; ++ibench) {

        // Initialization
        t0 = std::chrono::high_resolution_clock::now();
        sum = 0;

        // Loop of tests
        for (unsigned long long int itest = 1; itest <= ntests; ++itest) {
#ifdef _FIRST
            sum += f1((itest+sum)%primes[0], (itest+sum)%primes[1], (itest+sum)%primes[2], (itest+sum)%primes[3], (itest+sum)%primes[4], (itest+sum)%primes[5], (itest+sum)%primes[6], (itest+sum)%primes[7], (itest+sum)%primes[8], (itest+sum)%primes[9]);
#endif
#ifdef _SECOND
            sum += f2((itest+sum)%primes[0], (itest+sum)%primes[1], (itest+sum)%primes[2], (itest+sum)%primes[3], (itest+sum)%primes[4], (itest+sum)%primes[5], (itest+sum)%primes[6], (itest+sum)%primes[7], (itest+sum)%primes[8], (itest+sum)%primes[9]);
#endif
        }

        // Finalization
        result = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now()-t0).count();
        mean += result;
        std::cout<<"time = "<<result<<" (sum = "<<sum<<")"<<std::endl;
    }

    // End
    std::cout<<"mean time = "<<mean/nbenchs<<std::endl;
    return 0;
}

With 50 benchmarks for each solution with a given number of arguments, the dispersion is very small, and the mean time over these benchmarks is a reliable indicator.

My first benchmark has been with the "right" number of arguments where the Alon solution is faster than the AndyProwl solution.

The final results are here :

Benchmark

So the AndyProwl solution is generally faster than the Alon one. So, now I can validate your answer. But I think that the difference is so small that it's architecture/compiler dependent.

So:

  • AndyProwl+1 for your generally faster solution
  • Alon+1 for your constexpr-ready solution
like image 33
Vincent Avatar answered Sep 21 '22 23:09

Vincent


You can execute them separately and return a bool expression:

bool b0 = f(arg);
bool b1 = f(args);
return b0 && b1;
like image 20
user123 Avatar answered Sep 23 '22 23:09

user123