C++ 全力以赴,&;被处决?

C++ 全力以赴,&;被处决?,c++,templates,c++11,logic,variadic-templates,C++,Templates,C++11,Logic,Variadic Templates,考虑以下变量函数 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 } 模板 布尔f(类型和参数,类型和参数) { 返回

考虑以下变量函数

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
} 
模板
布尔f(类型和参数,类型和参数)
{
返回f(参数)和&f(参数…);
}
模板
布尔f(类型和参数)
{
//做点什么
} 

如果一个递归级别是
false
,那么我怀疑下面的代码将不会执行。是否有一种技巧可以强制所有参数递归,即使其中一个参数返回
false

这应该不会太难:

template <typename Type, typename... Types>
bool f(Type& arg, Types&... args)
{
    bool b1 = f(arg);
    bool b2 = f(args...);
    return b1 && b2;
}
模板
布尔f(类型和参数,类型和参数)
{
bool b1=f(arg);
boolb2=f(args…);
返回b1和b2;
}

您可以分别执行它们并返回布尔表达式:

bool b0 = f(arg);
bool b1 = f(args);
return b0 && b1;
没有递归:

template <typename... Types>
bool f(Types&&... args)
{
  bool r=true;
  (void)std::initializer_list<bool>{(r = f(args)&&r)...};
  return r;
}
模板
布尔f(类型和参数)
{
布尔r=真;
(void)std::初始值设定项列表{(r=f(args)&&r)…};
返回r;
}

有一个更好的技巧, 不要在所有函数之间使用&&而只使用一个函数&

static_cast(f(arg))和static_cast(f2(args))

... 无论结果如何,都将运行所有操作:)

由于在比较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;
}
#包括
#包括
//职能1:与&&
模板
内联布尔f1(常量类型和参数)
{
返回arg;
}
模板
内联布尔f1(常量类型和参数,常量类型和参数)
{
布尔arg1=f1(arg);
布尔arg2=f1(args…);
返回arg1&&arg2;
}
//职能2:与&
模板
内联布尔f2(常数类型和参数)
{
返回arg;
}
模板
内联布尔f2(常量类型和参数,常量类型和参数)
{
返回f2(arg)和f2(args…);
}
//基准
int main(int argc,char*argv[])
{
//变数
静态常量无符号长整型素数[10]={11,13,17,19,23,29,31,37,41,43};
静态常量无符号长整长整长nbenchs=50;
静态常量无符号长整数测试=10000000;
无符号长整型和=0;
双结果=0;
双平均值=0;
std::chrono::高分辨率时钟::时间点t0=std::chrono::高分辨率时钟::现在();
//基准循环
for(无符号长整型ibench=0;ibench对于(unsigned long long int itest=1;itest我想只需去掉对
f
@sftrabbit:Leftover:)的第二次调用,谢谢你为什么需要
f(arg)
?这不应该是
bool b1=arg
?这可以用
static\u cast
来修复。我喜欢这种方法,因为它比使用辅助变量的方法更紧凑。@Alon:在大多数情况下?这只意味着它将是一个更危险的错误。但是好吧,你“修复”了它,所以我收回了-1。但它不再“好”我不认为这是“更好的把戏”“它只会使代码更难读、调试和维护。@ Vincent:为什么不使用临时变量?如果没有这一点,就没有性能损失,如果这是你关心的,它会使你的意图变得清晰。这一点是不正确的。习惯于阅读C++的人实际上希望在读取代码时看到短路。这是一个,因为这是通常的行为,而且逻辑连接不经常使用
&
。你不必接受我的答案,只是请不要从中学习。@Vincent:这样做不会给你带来一点点性能提升,任何编译器都只会优化临时变量。如果编译器是真的很蠢,那么我认为它更有可能会给这个版本带来性能损失,因为对
bool
和按位&.@AndyProwl的转换:我必须检查程序集,但我刚刚对您的解决方案和这个解决方案做了4系列50个基准测试(没有静态_转换,因为f返回布尔值),这一个比你的(g++4.7.2和-O3)快7.5%。用
&
替换
&
怎么样?因为我已经发布了代码,你可以运行它几次并计算离散度。两种解决方案都是可互换的,编译器可以通过“仿佛”来执行其中一个而不是另一个原则。没有副作用,结果是相同的。因此,您的基准测试最多只能检测到潜在的优化失误。-1事实上,两种方法产生完全相同的代码,例如,对于两个参数的情况。请参阅。