将函数'a'传递给函数'b',并且需要"a"的参数列表。
Passing function 'a' to function 'b' and needing an argument list for 'a'.
作为"加速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;
}
有人建议,这个问题可以通过将谓词作为模板参数包括在内来解决。在上面的代码中,这个问题已经解决了,而无需添加另一个模板参数。使谓词成为返回布尔值的函子。
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数