在模板专门化中优化循环和避免代码重复

Optimizing loop and avoiding code duplication in a template specialization

本文关键字:代码 循环 专门化 优化      更新时间:2023-10-16

假设我们有一个函数

template< typename A, typename B, typename C >
void function(vector<A>& keyContainer, int a, int b, int c, boost::function<bool(B&)> selector, C* objPointer = NULL)
{
    BOOST_FOREACH(const A& key, keyContainer)
    {
        B* pVal = someGetObjFunction(objPointer, key);
        if(pVal)
        {
            if(selector && selector(*pVal))
            {
                pVal->someOtherFunction(1,2,3);
            }
            //some more code
        }
    }
}

这看起来很糟糕,因为它总是会进入

if(selector && selector(*pVal))

即使是NULL,修复这个问题的一个明显的方法是:

template< typename A, typename B, typename C >
void function(vector<A>& keyContainer, int a, int b, int c, boost::function<bool(B&)> selector, C* objPointer = NULL)
{
    if(selector)
    {
        BOOST_FOREACH(const A& key, keyContainer)
        {
            B* pVal = someGetObjFunction(objPointer, key);
            if(pVal)
            {
                if(selector(*pVal))
                {
                    pVal->someOtherFunction(1,2,3);
                }
                //some more code
            }
        }
    }
    else
    {
        BOOST_FOREACH(const A& key, keyContainer)
        {
            B* pVal = someGetObjFunction(objPointer, key);
            if(pVal)
            {
                pVal->someOtherFunction(1,2,3);
                //some more code
            }
        }
    }
}

但是这导致了大量的代码重复,另一种方法是在函数为NULL的情况下进行专门化,但这不与上面的例子几乎相同吗?有没有其他方法可以做到这一点,而不需要复制所有的代码?

你的问题描述有点令人困惑。您没有检查NULL,因为selector不是指针。相反,您要检查boost::function对象是否为empty()(参见:http://www.boost.org/doc/libs/1_55_0/doc/html/boost/function.html#idp54857000-bb)。

同样,你的两个代码块是不相等的。您似乎表明,如果(提供选择器 true) (未提供选择器),您想要执行内部循环。

所以,你的第一个代码块应该是:
template< typename A, typename B, typename C >
void function(vector<A>& keyContainer, int a, int b, int c, boost::function<bool(B&)> selector, C* objPointer = NULL)
{
    BOOST_FOREACH(const A& key, keyContainer)
    {
        B* pVal = someGetObjFunction(objPointer, key);
        if(pVal)
        {
            if(!selector || (selector && selector(*pVal)))
            {
                pVal->someOtherFunction(1,2,3);
            }
            //some more code
        }
    }
}

逻辑上等同于你的第二块代码。

正如Igor Tendetnik所提到的,您需要实际测量代码以查看瓶颈在哪里。很可能不是检查选择器是否为空。

如果检查选择器是否为空确实是你的瓶颈,这是不太可能的,因为打开优化的编译器将使这些比较非常快内联函数调用,你可以缓存空测试的结果。

template< typename A, typename B, typename C >
void function(vector<A>& keyContainer, int a, int b, int c, boost::function<bool(B&)> selector, C* objPointer = NULL)
{
    bool check_selector = !selector.empty();
    BOOST_FOREACH(const A& key, keyContainer)
    {
        B* pVal = someGetObjFunction(objPointer, key);
        if(pVal)
        {
            if(!check_selector || (check_selector && selector(*pVal)))
            {
                pVal->someOtherFunction(1,2,3);
            }
            //some more code
        }
    }
}