转发引用的参数类型检查不起作用

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();
}