考虑以下可变参数函数
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
?
答案 0 :(得分:21)
这不应该太难:
template <typename Type, typename... Types>
bool f(Type& arg, Types&... args)
{
bool b1 = f(arg);
bool b2 = f(args...);
return b1 && b2;
}
答案 1 :(得分:11)
随着辩论在AndyProwl和Alon解决方案的比较中得到发展,我已经对两种解决方案进行了基准测试,结果......取决于参数的数量。
编译:
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
对Alon解决方案进行基准测试。
以下是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个基准测试,分散度非常小,这些基准测试的平均时间是一个可靠的指标。
我的第一个基准是使用“正确”数量的参数,其中Alon解决方案比AndyProwl解决方案更快。
最终结果如下:
所以AndyProwl解决方案通常比Alon解决方案更快。所以,现在我可以验证你的答案。但我认为差异是如此之小,以至于它依赖于架构/编译器。
所以:
答案 2 :(得分:4)
您可以单独执行它们并返回bool表达式:
bool b0 = f(arg);
bool b1 = f(args);
return b0 && b1;
答案 3 :(得分:4)
没有递归:
template <typename... Types>
bool f(Types&&... args)
{
bool r=true;
(void)std::initializer_list<bool>{(r = f(args)&&r)...};
return r;
}
答案 4 :(得分:-1)
有一个更好的技巧, 而不是使用&amp;&amp;在所有功能之间,只需使用一个&amp;
static_cast<bool>(f(arg)) & static_cast<bool>(f2(args))
...无论结果如何都将运行所有操作:)