作为“加速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;
}
它是否与函数的返回类型为模板有关? 任何澄清将不胜感激!
答案 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 ()
的任何内容进行实例化,以第四种方式模板类型检查的一行(在您实例化In
和Out
之后)。 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的函子。