泛型函数中的模板参数 我正在解决加速C++的练习题,即

泛型函数中的模板参数 我正在解决加速C++的练习题,即,c++,templates,C++,Templates,实施我们在§8.2.5/148中使用的交换功能。我们为什么这么做 调用交换,而不是直接交换*beg和*end的值? 提示:试试看 书中的实际功能是 template<class Bi> void reverse(Bi begin, Bi end) { while (begin != end) { --end; if (begin != end) swap(*begin++, *end); } } 它起作用了,但我还是不明

实施我们在§8.2.5/148中使用的交换功能。我们为什么这么做 调用交换,而不是直接交换*beg和*end的值? 提示:试试看

书中的实际功能是

template<class Bi> void reverse(Bi begin, Bi end) {
while (begin != end) {
       --end;
        if (begin != end)
           swap(*begin++, *end);
     } }

它起作用了,但我还是不明白为什么第二个不起作用

编译器无法推断代码中的
X
。但是不需要为迭代器中包含的数据类型指定额外的模板类型
std::iterator
包含一个名为
value\u 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;
        }   
    }
}
模板
无效反向(Bi b、Bi e)
{
typename Bi::value_类型tmp;
while(b!=e){
--e;
如果(b!=e)
{
tmp=*b;
*b=*a;
*a=tmp;
--b;
}   
}
}

您的问题在于新引入的模板参数
X
,编译器无法确定该参数,因为它不依赖于参数。因此,
reverse
的调用方必须指定它。它们显然没有,因此编译器拒绝了代码

由于类型
X
实际上取决于传递给函数的迭代器类型,因此可以使用中的
value\u type
type。但是,这样做需要用户在
reverse
函数中使用高级迭代器,而您也不希望这样做

C++11必须解决类似的问题。但是您可能不希望代码依赖于全新的特性,因为许多编译器不支持它

此外,您的代码正在执行对象的不必要副本,以便将其移动到临时变量中或从临时变量中移动。对于没有复制操作符(或复制构造函数)的高级对象,这可能不起作用。在C++11中,同样存在右值引用和移动语义。但即使这样,也不可能有默认构造函数,因此您的代码将被破坏

理论上,您可以使用类型特征来确定传递给
reverse
的对象的类型,并使用模板专门化来实现不同的实现,但实际上<代码>交换使用函数重载,因此可以自动确定类型,它支持C++11等的移动语义。例如,如果它不是内联的,使用它可能会有问题,并且为每个元素推送/弹出帧。但事实并非如此

此外,
swap
本身也可以专门化。例如,对于POD类型,它可以使用
XOR
交换两个元素的内容,而无需创建额外的副本。不管怎样,现代编译器都会为您这样做,但这只是一个想法


因此,最好使用
swap
:)

如何调用
reverse(Bi b,Bi e)
?在第二种情况下,编译器应该如何知道它需要什么样的模板参数
X
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);
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;
        }   
    }
}