优化循环并避免模板特化中的代码重复

时间:2014-08-16 12:52:23

标签: c++ loops templates optimization specialization

假设我们有一个功能

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的情况下对这种情况进行专门化,但不会像上面的例子那样几乎相同吗?有没有其他方法可以做到这一点而不重复所有代码?

1 个答案:

答案 0 :(得分:1)

您的问题描述有点令人困惑。您没有检查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所提到的,您需要实际测量代码以查看瓶颈所在。它可能不是检查选择器是否为空。

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

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