令人困惑的C ++模板

时间:2013-05-17 05:04:59

标签: c++ templates struct rvalue-reference typename

我正在学习C ++模板。有人可以解释这段代码的每一点

template <class T>
struct identity
{
    typedef T type;
};
template <class T>
T&& forward(typename identity<T>::type&& a)
{
    return a;
}

2 个答案:

答案 0 :(得分:2)

首先,您需要my_forward的另一个专门化来允许此调用:

int a;
my_forward<int>(a);

所以,对这样的引用进行专门化my_forward

template <class T>
T&& my_forward(typename identity<T>::type& a)
{
    return static_cast<T&&>(a);
}

但在这种情况下,请致电

int a;
my_forward<int&>(std::ref(a));

含糊不清:

note: candidate function [with T = int &]
T&& my_forward(typename identity<T>::type&& a)
    ^
note: candidate function [with T = int &]
T&& my_forward(typename identity<T>::type& a)
    ^

为避免这种情况,您应该使用std::remove_reference而不仅仅是identity

template <class T>
T&& my_forward(typename std::remove_reference<T>::type&& a)
{
    return static_cast<T&&>(a);
}

template <class T>
T&& my_forward(typename std::remove_reference<T>::type& a)
{
    return static_cast<T&&>(a);
}

答案 1 :(得分:2)

template <class T>
struct identity
{
    typedef T type;
};

这部分定义了一个名为identity的类模板,它保存了作为模板参数传递的类型的typedef公共成员type。在您的示例中,没有部分或显式特化,因此传递给identity的任何类型都是type

template <class T>
T&& forward(typename identity<T>::type&& a)
{
    return a;
}

forward是一个函数模板,它采用对identity<T>::type返回的类型的rvalue-reference。 type返回的类型(无论多么明显)都不能被编译器推导为T(因为类型是dependent type),所以你必须明确指定模板参数forward

rvalue-reference语法&&(对于return-type)也表示什么是(非正式地)称为通用引用,因为类型T是一个模板参数。这意味着return-type可以绑定到函数返回的rvalues和lvalues。

参数类型identity<T>::type&& 是通用引用,因为返回的类型不是模板参数。这意味着参数只能接受rvalues。这将要求我们move左右进入forward的参数:

int main()
{
    int n{0};
    forward<int>(std::move(n));
}

最后我们将参数a返回到右值引用。但请注意,将参数返回T&&将无效,因为a必须移动

template <class T>
T&& forward(typename identity<T>::type&& a)
{
    return std::move(a);
}

否则返回一个左值引用:

template <class T>
T& forward(typename identity<T>::type&& a)
{
    return a;
}