使用模板函数生成的代码与普通函数之间的差异

Nav*_*een 3 c++ compiler-construction templates code-generation

我有一个包含大量元素的向量.现在我想编写一个小函数来计算向量中偶数或奇数元素的数量.由于性能是一个主要问题,我不想在循环中放入if语句.所以我写了两个小函数,如:

long long countOdd(const std::vector<int>& v)
{
    long long count = 0;
    const int size = v.size();
    for(int i = 0; i < size; ++i)
    {
        if(v[i] & 1)
        {
            ++count;
        }
    }
    return count;
}

long long countEven(const std::vector<int>& v)
{
    long long count = 0;
    const int size = v.size();
    for(int i = 0; i < size; ++i)
    {
         if(0 == (v[i] & 1))
        {
            ++count;
        }
    }
    return count;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是我可以通过编写这样的单个模板函数来获得相同的结果:

template <bool countEven>
long long countTemplate(const std::vector<int>& v1)
{
    long long count = 0;
    const int size = v1.size();
    for(int i = 0; i < size; ++i)
    {
        if(countEven)
        {
            if(v1[i] & 1)
            {
                ++count;
            }
        }
        else if(0 == (v1[i] & 1))
        {
            ++count;
        }
    }
    return count;
}
Run Code Online (Sandbox Code Playgroud)

并使用它像这样:

int main()
{
  if(somecondition)
  {
     countTemplate<true>(vec); //Count even
  }      
  else
  {
     countTemplate<false>(vec); //Count odd
  } 
}
Run Code Online (Sandbox Code Playgroud)

为模板和非模板版本生成的代码是否相同?还是会发出一些额外的指示?

请注意,数字的计数仅用于说明,因此请不要建议其他计数方法.

编辑:好的.我同意从性能的角度来看它可能没什么意义.但至少从可维护性的角度来看,我希望只有一个函数来维护而不是两个.

xto*_*ofl 10

模板化版本可能并且很可能在编译器看到代码中的某个分支从未到达时进行优化.该countTemplate例如代码,将有countEven模板参数设置为true,所以奇数分支会被切掉.

(对不起,我不禁建议另一种计数方法)

在这种特殊情况下,您可以count_if在矢量上使用:

struct odd { bool operator()( int i )const { return i&1; } };
size_t nbOdd = std::count_if( vec.begin(), vec.end(), odd() );
Run Code Online (Sandbox Code Playgroud)

这也可以进行优化,并且编写方式更短:)标准库开发人员已经考虑了可能的优化,所以最好尽可能使用它,而不是编写自己的计数for循环.

  • 而countEven当然实现为`v.size() - countOdd(v);` (2认同)

jal*_*alf 6

您的模板版本将生成如下代码:

template <>
long long countTemplate<true>(const std::vector<int>& v1)
{
    long long count = 0;
    const int size = v1.size();
    for(int i = 0; i < size; ++i)
    {
        if(true)
        {
                if(v1[i] & 1)
                {
                        ++count;
                }
        }
        else if(0 == (v1[i] & 1))
        {
                ++count;
        }
    }
    return count;
}


template <>
long long countTemplate<false>(const std::vector<int>& v1)
{
    long long count = 0;
    const int size = v1.size();
    for(int i = 0; i < size; ++i)
    {
        if(false)
        {
                if(v1[i] & 1)
                {
                        ++count;
                }
        }
        else if(0 == (v1[i] & 1))
        {
                ++count;
        }
    }
    return count;
}
Run Code Online (Sandbox Code Playgroud)

因此,如果禁用所有优化if,理论上的意愿仍然存在.但即使是一个非常天真的编译器也会确定你正在测试一个常量,并简单地删除它if.

所以在实践中,不,生成的代码应该没有区别.所以你可以使用模板版本,不用担心这个.