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

时间:2013-09-02 22:19:09

标签: c++ stl

作为“加速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;
}

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

6 个答案:

答案 0 :(得分:3)

因为在第一个例子中,function的类型是模板化的。从本质上讲,T 确实将返回类型和参数列表作为其类型的一部分。但由于它是模板化类型,因此您没有明确说出它(相反,编译器会从调用代码中推断出它)。

在第二个实例中,predicate 模板化。其类型明确说明。本来可以将它模板化,但无论出于什么原因都没有做到。

答案 1 :(得分:1)

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

  • 的返回类型可转换为*dest
  • 类型
  • 可以转换*begin的参数。

第二个函数仅在传入函数时返回bool,取double参数。

所以第一个更通用。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

在第一种情况下,您要求编译器推导出它愉快地执行的函数对象类型。

答案 4 :(得分:0)

在第一种情况下,您对function的所有了解都是T类型,可以使用支持operator ()的任何内容进行实例化,以第四种方式模板类型检查的一行(在您实例化InOut之后)。 T可以是函数类型,但不需要。

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

答案 5 :(得分:0)

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

有人建议通过将谓词作为模板参数来解决这个问题。在上面的代码中,这已经解决了,而没有添加另一个模板参数。使谓词成为一个返回bool的函子。