2013-03-23 10 views
8

निम्नलिखित variadic समारोह पर विचार करेंसभी एंड को निष्पादित करने के लिए मजबूर करें?

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 
} 

तो प्रत्यावर्तन में से एक स्तर false है, तो मुझे लगता है कि निम्नलिखित निष्पादित नहीं किया जाएगा। क्या सभी तर्कों पर रिकर्सन को मजबूर करने के लिए कोई चाल है, भले ही उनमें से कोई false लौटाता है?

+1

के लिए के लिए कैसे जगह '' && साथ 'और' के बारे में? – fredoverflow

उत्तर

21

यह बहुत कठिन नहीं होना चाहिए:

template <typename Type, typename... Types> 
bool f(Type& arg, Types&... args) 
{ 
    bool b1 = f(arg); 
    bool b2 = f(args...); 
    return b1 && b2; 
} 
+0

मुझे लगता है कि 'f' पर दूसरी कॉल से छुटकारा पाएं। –

+0

@sftrabbit: बचे हुए :) धन्यवाद –

+0

बेंचमार्क के लिए मेरा जवाब देखें। – Vincent

4

आप उन्हें अलग से निष्पादित और एक bool अभिव्यक्ति लौट सकते हैं:

template <typename... Types> 
bool f(Types&&... args) 
{ 
    bool r=true; 
    (void)std::initializer_list<bool>{(r = f(args)&&r)...}; 
    return r; 
} 
4

प्रत्यावर्तन के बिना &का उपयोग करने के बजाए बहुत अच्छी चाल, सभी कार्यों के बीच, बस का उपयोग एक &

static_cast<bool>(f(arg)) & static_cast<bool>(f2(args)) ... सभी कार्यों पर ध्यान दिए बिना परिणाम :)

-1

वहाँ एक है:

bool b0 = f(arg); 
bool b1 = f(args); 
return b0 && b1; 
+0

जब तक वे 'बूल' के बजाय 'int' वापस नहीं करते हैं और मान' 1' और '2' होते हैं और आपको अचानक 'सत्य' के बजाय 'झूठा' मिलता है। क्षमा करें, -1। –

+1

इसे 'static_cast 'के साथ ठीक किया जा सकता है। मुझे इस दृष्टिकोण को पसंद है क्योंकि यह सहायक चर के साथ अधिक कॉम्पैक्ट है। – ipc

+0

मुझे यह भी पसंद है, बूलियन के लिए int कास्टिंग आसान है, और यह अच्छा और कॉम्पैक्ट है :), बहुत बुरी चालें ऐसे नकारात्मक वोट उत्पन्न करती हैं: डी, ​​@Ipc टिप्पणी के कारण संपादित – Alon

11

की बहस AndyProwl और एलन समाधान की तुलना में विकसित किया गया है के रूप में चलाया जाएगा, मैं दोनों समाधानों का बेंचमार्क किया है, और नतीजा ... तर्कों की संख्या पर निर्भर करता है।

साथ संकलन:

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

मानक AndyProwl समाधान और साथ संकलन:

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

मानक एलन समाधान।

यहां 10 तर्कों के लिए बेंचमार्क का कार्यक्रम है।

#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; 
} 

तर्क की दी गई संख्या के साथ प्रत्येक समाधान के लिए 50 मानक के साथ, फैलाव बहुत छोटा है, और इन मील के पत्थरों से अधिक मतलब समय एक विश्वसनीय संकेतक है।

मेरा पहला बेंचमार्क उन तर्कों की "दाएं" संख्या के साथ रहा है जहां एलोन समाधान एंडीप्रोएल समाधान से तेज़ है।

अंतिम परिणाम यहां हैं:

Benchmark

तो AndyProwl समाधान आम तौर पर तेजी एलन एक से है। तो, अब मैं आपके उत्तर को प्रमाणित कर सकता हूं। लेकिन मुझे लगता है कि अंतर इतना छोटा है कि यह वास्तुकला/कंपाइलर निर्भर है।

तो:

  • AndyProwl +1 अपने आम तौर पर तेजी समाधान
  • एलन + 1 आपके constexpr के लिए तैयार समाधान
+2

अच्छा ग्राफ, जानकारी साझा करने के लिए धन्यवाद। +1 –

+0

सभी ग्राफों को त्रुटि बार – Inverse

+0

की आवश्यकता है क्योंकि मैंने कोड पोस्ट किया है, आप इसे कई बार चला सकते हैं और फैलाव की गणना कर सकते हैं। – Vincent

संबंधित मुद्दे

 संबंधित मुद्दे