1

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

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

4

6 回答 6

3

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

在第二种情况下,没有predicate模板化。其类型已明确说明。可以将其模板化,但无论出于何种原因,都没有这样做。

于 2013-09-02T22:24:03.023 回答
1

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

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

bool仅当您传入一个函数、返回、接受一个double参数时,第二个函数才会起作用。

所以第一个更通用。

于 2013-09-02T22:26:36.510 回答
0

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

于 2013-09-02T22:23:30.213 回答
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;
}

有人建议可以通过将谓词作为模板参数来解决这个问题。在上面的代码中,这个问题在没有添加另一个模板参数的情况下得到了解决。使谓词成为返回布尔值的函子。

于 2013-09-03T20:44:47.840 回答
0

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

在第一种情况下,您要求编译器推断出它很乐意执行的函数对象类型。

于 2013-09-02T22:24:57.090 回答
0

在第一种情况下,您所知道function的只是它具有 type T,它可以用任何支持 的东西来实例化,operator ()这样模板的第四行就会进行类型检查(在您实例化之后InOutT可以是函数类型,但不需要。

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

于 2013-09-02T22:26:43.190 回答