转发引用的参数类型检查不起作用
Parameter type check for forwarding reference is not working
我正在尝试编写一个只接受 std::vector
作为参数的模板函数。然而,我想出的只适用于普通或左值参数,而不适用于转发引用参数。
以下代码无法编译。
template <typename T, typename = typename std::enable_if< std::is_same<T, std::vector< typename T::value_type, typename T::allocator_type > >::value>::type >
int f(T && a) {
return a.size();
}
int main() {
std::vector<int> a;
f(a);
}
但是,如果我将 f
的参数类型替换为左值引用或按值类型传递,如:
template <typename T, typename = typename std::enable_if< std::is_same<T, std::vector< typename T::value_type, typename T::allocator_type > >::value>::type >
int f(T a) {
return a.size();
}
比它编译。
请注意,我需要将 f 的参数作为转发引用。
我错过了什么?
如果你只想接受向量,那么你的代码可以大大简化。您可以不使用 SFINAE,而是指定您想要一个带有任何类型参数的 std::vector
。那看起来像
template <typename... Pack>
int f(std::vector<Pack...>const & a)
{
return a.size();
}
您的 SFINAE 方法不起作用的原因是当您将左值传递给函数时 T
被推断为引用类型。在执行
之类的事情时,引用类型不像类型本身那样工作
typename T::value_type
要解决这个问题,您需要使用 std::remove_reference
删除 T
的引用。那会给你一个像
这样的函数
template <typename T, typename VecType = typename std::remove_reference<T>::type, typename = typename std::enable_if< std::is_same<VecType, std::vector< typename VecType::value_type, typename VecType::allocator_type > >::value>::type >
int f(T && a) {
return a.size();
}
我正在尝试编写一个只接受 std::vector
作为参数的模板函数。然而,我想出的只适用于普通或左值参数,而不适用于转发引用参数。
以下代码无法编译。
template <typename T, typename = typename std::enable_if< std::is_same<T, std::vector< typename T::value_type, typename T::allocator_type > >::value>::type >
int f(T && a) {
return a.size();
}
int main() {
std::vector<int> a;
f(a);
}
但是,如果我将 f
的参数类型替换为左值引用或按值类型传递,如:
template <typename T, typename = typename std::enable_if< std::is_same<T, std::vector< typename T::value_type, typename T::allocator_type > >::value>::type >
int f(T a) {
return a.size();
}
比它编译。
请注意,我需要将 f 的参数作为转发引用。
我错过了什么?
如果你只想接受向量,那么你的代码可以大大简化。您可以不使用 SFINAE,而是指定您想要一个带有任何类型参数的 std::vector
。那看起来像
template <typename... Pack>
int f(std::vector<Pack...>const & a)
{
return a.size();
}
您的 SFINAE 方法不起作用的原因是当您将左值传递给函数时 T
被推断为引用类型。在执行
typename T::value_type
要解决这个问题,您需要使用 std::remove_reference
删除 T
的引用。那会给你一个像
template <typename T, typename VecType = typename std::remove_reference<T>::type, typename = typename std::enable_if< std::is_same<VecType, std::vector< typename VecType::value_type, typename VecType::allocator_type > >::value>::type >
int f(T && a) {
return a.size();
}