我正在解决加速c ++的运动问题,这是
实现我们在§8.2.5/ 148中使用的交换函数。我们为什么这样做 调用swap而不是直接交换* beg和* end的值? 提示:试一试,看看。
书中的实际功能是
template<class Bi> void reverse(Bi begin, Bi end) {
while (begin != end) {
--end;
if (begin != end)
swap(*begin++, *end);
} }
我改成了这个
template<class Bi,class X>
void reverse(Bi b, Bi e)
{
X tmp;
while (b!= e) {
--e;
if (b != e)
{
tmp=*b;
*b=*a;
*a=tmp;
--b;
}
}
}
它没有用,给出了以下错误。
没有匹配的呼叫功能 反向(标准::向量:迭代,性病::矢量:迭代)'
比我变成了这个
template<class Bi,class X>
void reverse(Bi b, Bi e,X c)
{
X tmp=c;
while (b!= e) {
--e;
if (b != e)
{
tmp=*b;
*b=*a;
*a=tmp;
--b;
}
}
}
并将上述功能称为
reverse(v.begin(),v.end(),0);
它有效,但我仍然没有弄清楚为什么第二个不工作?
答案 0 :(得分:2)
编译器无法推断代码中的X
。但是没有必要为迭代器中包含的数据类型指定额外的模板类型。 std::iterator
包含一个名为value_type
的typedef,用于实现这个目的:
template<class Bi>
void reverse(Bi b, Bi e)
{
typename Bi::value_type tmp;
while (b!= e) {
--e;
if (b != e)
{
tmp=*b;
*b=*a;
*a=tmp;
--b;
}
}
}
答案 1 :(得分:1)
您的问题在于新引入的模板参数X
,编译器无法确定该参数,因为它不依赖于参数。因此,reverse
的呼叫者必须指定它。它们显然没有,因此编译器拒绝代码。
因为类型X
实际上依赖于传递给函数的迭代器类型,所以您可以使用iterator_traits
中的value_type
类型。但是,这样做需要用户使用具有reverse
功能的高级迭代器,您不想这样做。
C ++ 11有decltype
来解决类似的问题。但是您可能不希望代码依赖于全新的功能,因为许多编译器不支持它。
此外,您的代码正在执行对象的不必要副本,以将其移入和移出临时变量。对于没有复制操作符(或复制构造函数)的高级对象,这可能不起作用。在C ++ 11中,还有rvalue引用和移动语义。但即便如此 - 可能没有默认的构造函数,所以你的代码会破坏。
理论上,您可以使用类型特征来确定传递给reverse
的对象的类型,并使用模板特化来提出不同的实现,但实际上...... swap
正在使用函数重载所以类型可以自动确定,它支持C ++ 11等的移动语义。如果没有内联,使用它会是一个问题,例如,为每个元素推送/弹出框架。但事实并非如此。
此外,swap
可以自己专门化。例如,对于POD类型,它可以使用XOR
来交换两个元素的内容,而无需创建额外的副本。现代编译器无论如何都会为你做这件事,但只是一个想法......
所以你最好使用swap
:)