将函数'a'传递给函数'b',并且需要"a"的参数列表。

Passing function 'a' to function 'b' and needing an argument list for 'a'.

本文关键字:函数 参数 列表      更新时间:2023-10-16

作为"加速C++"的练习,我正在重新实现算法标头中的一些基本 STL 算法。我想知道为什么在某些情况下,我们需要包含要传递给另一个函数的函数的参数列表,而其他时候,我们只需要包含函数名称。我看不出这背后的逻辑。

例:

// In this case, I just need to include the 'function' name in the parameter list.
template <class In, class Out, class T>
Out transform(In begin, In end, Out dest, T function) {
    while (begin != end) {
        *dest++ = function(*begin++);        
    }
    return dest;
}
// In this case, 'predicate' requires a parameter list.
template <class In, class Out>
Out remove_copy_if(In begin, In end, Out dest, bool predicate(double x)) {
    while (begin != end) {
        if (!predicate(*begin)) {
            *dest++ = *begin;
        }
        ++begin;
    }
    return dest;
}

它与函数的返回类型是模板有关吗?任何澄清将不胜感激!

因为首先,function 的类型是模板化的。实质上,T确实将返回类型和参数列表作为其类型的一部分。但是由于它是一个模板化类型,所以你不会明确地说出来(相反,编译器从调用代码中推断出它(。

在第二个实例中,predicate模板化。其类型已明确说明。本来可以对其进行模板化,但无论出于何种原因,都没有这样做。

第一个示例函数将适用于以下每个函数或函子(函数对象 [具有重载operator()的类](

  • 具有可转换为*dest类型的返回类型,并且
  • *begin可以转换为的参数。

第二个函数只有在传入函数时才会起作用,返回 bool ,采用double参数。

所以第一个更通用。

第一种情况将所有元素从 begin 转换为 end 。第二种情况仅复制 predicate() 不为该元素返回 True 的那些。因此,predicate()必须将元素传递给它,以便它可以决定它应该返回 True 还是 False。

在第二种情况下,你有一个非常具体的谓词类型,即一个函数接受一个double并返回一个bool,而不是一个可以用double调用的任意函数对象并返回一个bool。由于您不尝试推断函数对象的类型,因此您需要指定类型!

在第一种情况下,你要求编译器推断出它很高兴的函数对象类型。

在第一种情况下,您对function的了解只是它具有类型 T ,它可以使用任何支持operator ()的东西来实例化,以这样的方式,模板的第四行进行类型检查(在您实例化In之后,也Out(。 T可以是函数类型,但不需要。

在第二种情况下,predicate是一个接受double并返回bool的函数。

class predicate
{
int i;
 public:
predicate() {}; 
bool operator()(int x){ return x > 6;};
};
template <class In, class Out>
Out remove_copy_if(In begin, In end, Out dest, predicate& pred) {
while (begin != end) {      
    if (!pred(*begin)) {
        *dest++ = *begin;
        }
    ++begin;
    }
    return dest;
}
int main() {
vector <int> v1, v2(10);
vector <int>::iterator Iter1, Iter2, new_end;
int i;
for ( i = 0 ; i <= 9 ; i++ )
  v1.push_back( i );
int ii;
for ( ii = 0 ; ii <= 3 ; ii++ )
   v1.push_back( 7 );
random_shuffle ( v1.begin( ), v1.end( ) );
cout << "The original vector v1 is:      ( " ;
for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
   cout << *Iter1 << " ";
cout << ")." << endl;
predicate p;
// Remove elements with a value greater than 6
new_end = remove_copy_if ( v1.begin( ), v1.end( ), 
   v2.begin( ), p );
cout << "After the appliation of remove_copy_if to v1,n "
     << "vector v1 is left unchanged as ( " ;
for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ )
   cout << *Iter1 << " ";
cout << ")." << endl;
cout << "Vector v2 is a copy of v1 with values greater "
     << "than 6 removed:n ( " ;
for ( Iter2 = v2.begin( ) ; Iter2 != new_end ; Iter2++ )
       cout << *Iter2 << " ";
   cout << ")." << endl;
}

有人建议,这个问题可以通过将谓词作为模板参数包括在内来解决。在上面的代码中,这个问题已经解决了,而无需添加另一个模板参数。使谓词成为返回布尔值的函子。