C++ 模板显式右值类型
C++ Template explicit rvalue type
#include <iostream>
using namespace std;
namespace mine {
template <typename T>
struct remove_rval {
using type = T;
};
template <typename T>
struct remove_rval<T&&> {
using type = T;
};
template <typename T>
void g(const T& = typename remove_rval<T>::type())
cout << __PRETTY_FUNCTION__ << endl;
}
}
int main()
{
mine::g<int&&>(); // doesn't work, because of explicit template?
const int& i2 = mine::remove_rval<int&&>::type(); // works, sanity check
return 0;
}
我写的函数模板编译失败。根据我对 c++ 的理解,您可以将右值分配给常量左值引用。但是,在这种情况下,就像推导类型在分配函数默认值时忽略 'const' 限定符一样。这是为什么?
void g(const T& = typename remove_rval<T>::type())
当 T = U&&
时,引用折叠规则使 const T&
等于 U&
。 Lvalue-references 无法绑定到像 remove_rval<T>::type()
这样的临时对象。您可以简单地将 int
作为模板参数传递,参数的类型将正确地为 const int&
.
来自 dcl.ref/p6:
If a typedef-name ([dcl.typedef], [temp.param]) or a decltype-specifier ([dcl.type.decltype]) denotes a type TR that is a reference to a type T, an attempt to create the type lvalue reference to cv TR
creates the type lvalue reference to T
, while an attempt to create the type rvalue reference to cv TR creates the type TR
.
因此在您的示例中,当 T = int&&
时:
const T&
折叠为 T&
(即 int&
)和 而不是 const T&
(即 const int&
)以上引用的声明。而且由于我们不能将 rvalue 像 remove_rval<T>::type()
绑定到 non-const 左值引用 ,你会得到提到的错误.
因此,即使 g
中函数参数的形式是 对 const T
的引用,又名 const 左值引用(即 const T&
),第一次调用 g
实例化 g
引用 non-const T
又名 non-const 左值引用 (即 T&
=int&
) 作为参数:
template<>
void g<int &&>(int&)
{
//operator<< called here
}
并且因为参数是 int&
,我们不能像 remove_rval<int&&>::type()
这样的 rvalue 绑定到那个参数。
#include <iostream>
using namespace std;
namespace mine {
template <typename T>
struct remove_rval {
using type = T;
};
template <typename T>
struct remove_rval<T&&> {
using type = T;
};
template <typename T>
void g(const T& = typename remove_rval<T>::type())
cout << __PRETTY_FUNCTION__ << endl;
}
}
int main()
{
mine::g<int&&>(); // doesn't work, because of explicit template?
const int& i2 = mine::remove_rval<int&&>::type(); // works, sanity check
return 0;
}
我写的函数模板编译失败。根据我对 c++ 的理解,您可以将右值分配给常量左值引用。但是,在这种情况下,就像推导类型在分配函数默认值时忽略 'const' 限定符一样。这是为什么?
void g(const T& = typename remove_rval<T>::type())
当 T = U&&
时,引用折叠规则使 const T&
等于 U&
。 Lvalue-references 无法绑定到像 remove_rval<T>::type()
这样的临时对象。您可以简单地将 int
作为模板参数传递,参数的类型将正确地为 const int&
.
来自 dcl.ref/p6:
If a typedef-name ([dcl.typedef], [temp.param]) or a decltype-specifier ([dcl.type.decltype]) denotes a type TR that is a reference to a type T, an attempt to create the type lvalue reference to cv
TR
creates the type lvalue reference toT
, while an attempt to create the type rvalue reference to cv TR creates the typeTR
.
因此在您的示例中,当 T = int&&
时:
const T&
折叠为 T&
(即 int&
)和 而不是 const T&
(即 const int&
)以上引用的声明。而且由于我们不能将 rvalue 像 remove_rval<T>::type()
绑定到 non-const 左值引用 ,你会得到提到的错误.
因此,即使 g
中函数参数的形式是 对 const T
的引用,又名 const 左值引用(即 const T&
),第一次调用 g
实例化 g
引用 non-const T
又名 non-const 左值引用 (即 T&
=int&
) 作为参数:
template<>
void g<int &&>(int&)
{
//operator<< called here
}
并且因为参数是 int&
,我们不能像 remove_rval<int&&>::type()
这样的 rvalue 绑定到那个参数。