将类似的函数组合成一个通用函数,包括将函数指针作为参数传递

时间:2009-05-27 17:50:10

标签: c++

我试图将以下两个函数组合成一个便携函数:

void NeedleUSsim::FindIdxRho()
{
    searchTmp = &ninfo->rho;
    double *p = std::find_if(tplRho_deg, tplRho_deg+sampleDim[2], &NeedleUSsim::GreaterThanOrEqualTo);
    while(p != tplRho_deg+sampleDim[2])
    {
        idxRho = p - tplRho_deg;
        p = std::find_if(p+1, tplRho_deg+sampleDim[2], &NeedleUSsim::GreaterThanOrEqualTo);
    }
}

void NeedleUSsim::FindIdxDepth()
{
    searchTmp = &ninfo->l;
    double *p = std::find_if(tplL, tplL+sampleDim[1], &NeedleUSsim::LessThanOrEqualTo);
    while(p != tplL+sampleDim[1])
    {
        idxL = p - tplL;
        p = std::find_if(p+1, tplL+sampleDim[1], &NeedleUSsim::LessThanOrEqualTo);
    }
}

理想情况下,我希望函数的参数将tpl成员作为指针传递,并将大小和rho / l作为值传递。 searchTmp是一个文件范围双精度指针。有没有简单的方法将& NeedleUSsim :: GreaterThanOrEqualTo函数作为我正在尝试编写的函数的参数传递?

提前感谢您的建议。

5 个答案:

答案 0 :(得分:6)

使代码更通用的最简单方法如下:

template<typename ComparisonType>
double* NeedleUSsim::FindIdx(double* containerBegin, double* containerEnd, ComparisonType comparison) {
    double* p = std::find_if(containerBegin, containerEnd, comparison);
    double* idx = 0;
    while(p != containerEnd)
    {
        idx = p - containerBegin;
        p = std::find_if(p+1, containerEnd, comparison);
    }
    return idx;
}

void NeedleUSsim::FindIdxRho()
{
  searchTmp = &ninfo->rho;
  double* idx = FindIdx(tplRho_deg, tplRho_deg+sampleDim[2], &NeedleUSsim::GreaterThanOrEqualTo);
  if( idx != 0 )
  {
    idxL = idx;
  }

}

void NeedleUSsim::FindIdxDepth()
{
  searchTmp = &ninfo->l;
  double* idx = FindIdx(tplL, tplL+sampleDim[1], &NeedleUSsim::LessThanOrEqualTo);
  if( idx != 0 )
  {
    idxRho = idx;
  }
}

答案 1 :(得分:3)

  

有没有简单的方法将&amp; NeedleUSsim :: GreaterThanOrEqualTo函数作为我正在尝试编写的函数的参数传递?

有几种方法可以做到这一点。

  1. 您可以传递
  2. 周围的函数指针
  3. 您可以使用运行时多态性
  4. 创建并传递函数对象
  5. 您可以在函数对象(编译时多态性)上模板化您的公共函数
  6. eJames上面介绍了第一种方法。

    选项2

    第二种方法涉及将比较函数包装在某个函数 - 对象层次结构中。函数对象是类()运算符重载的实例。这使得实例可以调用:

     class IComparator
     {
     public:
        virtual bool operator()(lhs, rhs) = 0;
     }
    
    
     class CComparatorLessThan : public IComparator
     {
     public:
        virtual bool operator()(lhs, rhs) {...}
     }
    
    
     class CComparatorGreaterThan : public IComparator
     {
     public:
        virtual bool operator()(lhs, rhs) {...}
     }
    

    您的常用函数将采用ICompatator引用,并且行为将在运行时动态绑定。

    选项3

    第三种方法涉及模板化而不是创建对象层次结构

    template <class Comparator>
    void foo(...)
    {
       ...
       Comparator comparer;
       std::find_if(..., comparer);
    }
    

    然后调用foo将涉及:

    foo<CComparatorGreaterThan>(...);
    

    这消除了第二个解决方案的大量运行时开销。在这里,您不必定义基类。你只需要有某种类运算符()重载并返回bool。

答案 2 :(得分:1)

可以将成员函数指针传递给函数,如下所示:

typedef bool (NeedleUSsim::*compFunctionPtr)(NeedleUSsim &x, NeedleUSsim &y);

void NeedleUSsim::FindIdxRho(compFunctionPtr comparison)
{
    //..
    p = std::find_if(tplRho_deg, tplRho_deg+sampleDim[2], comparison);
    //..
}

然后可以这样调用:

//..
someNeedleUSsim.FindIdxRho(&NeedleUSsim::LessThanOrEqualTo);
//..

有关详细信息,请查看this C ++ FAQ Lite文章。

答案 3 :(得分:1)

将函数和更复杂的参数放入函数的简单方法是对它们进行模板化(我猜测某些参数类型)

template <typename F>
void NeedleUSsim::FindIdx(double *ninfoMember, double *tplParam, size_t dimension, F CompareFunc, int &target)
{
    searchTmp = ninfoMember;
    double *p = std::find_if(tplParam, tplParam+sampleDim[dimension], CompareFunc);
    while(p != tplParam+sampleDim[dimension])
    {
        target= p - tplParam;
        p = std::find_if(p+1, tplParam+sampleDim[dimension], CompareFunc);
    }
}

然后叫它:

FindIdx(&ninfo->rho, tplRho_deg, 2, &NeedleUSsim::GreaterThanOrEqualTo, idxRho);
FindIdx(&ninfo->l, tplL, 1, &NeedleUSsim::LessThanOrEqualTo, idxL);

答案 4 :(得分:1)

double *p = std::find_if(b, e, &NeedleUSsim::GreaterThanOrEqualTo);
while(p != e)
{
    idxRho = p - b;
    p = std::find_if(p + 1, e, &NeedleUSsim::GreaterThanOrEqualTo);
}

请注意,您使用的此循环不是必需的。使用反向迭代器

std::reverse_iterator<double*> rb(e), re(b);
rb = std::find_if(rb, re, &NeedleUSsim::GreaterThanOrEqualTo);
if(rb != re) {
    idxRho = re - rb;
}

现在它的作用更加明显。如果只在发现某些内容时写入idxRho是错误或无关紧要,可以将其缩短为此

std::reverse_iterator<double*> rb(e), re(b);
idxRho = re - std::find_if(rb, re, &NeedleUSsim::GreaterThanOrEqualTo);