混淆c++模板

Confusing C++ Template

本文关键字:模板 c++ 混淆      更新时间:2023-10-16

我正在学习c++模板。谁能解释一下这段代码的每一点

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

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

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

forward是一个函数模板,接受对identity<T>::type返回类型的右值引用。type返回的类型(无论多么明显)不能被编译器推断为T(因为该类型是依赖类型),因此必须显式指定forward的模板参数。

右值引用语法&&(用于返回类型)还表示(非正式地)称为通用引用,因为类型T是模板参数。这意味着返回类型可以绑定到函数返回的左值和右值。

形参类型identity<T>::type&&而不是通用引用,因为返回的类型不是模板形参。这意味着参数只能接受右值。这就要求我们将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;
}

首先,您需要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);
}