【问题标题】:Parameter type check for forwarding reference is not working转发引用的参数类型检查不起作用
【发布时间】:2020-03-07 10:07:00
【问题描述】:

我正在尝试编写一个只接受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 参数作为转发引用。

我错过了什么?

【问题讨论】:

  • 在转发引用版本T被推断为vector&lt;int&gt;&amp;,所以你不能只使用T,你需要通过std::remove_reference_t&lt;T&gt;丢弃该类型的引用。 Demo
  • 是的,你是对的! @rafix07

标签: c++ templates forwarding-reference


【解决方案1】:

如果您只想接受向量,那么您的代码可以简化很多。除了使用 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();
}

【讨论】:

  • 是的,但我不能将参数 a 设为转发引用。我会将其添加为注释。谢谢。
  • @OzgurMurat 刚刚更新了答案。您不需要转发参考。你可以只引用 const,除非你的实际代码不同?
  • 这只是为了演示我的问题。实际代码不同。
猜你喜欢
  • 2018-07-23
  • 1970-01-01
  • 2018-11-21
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 2014-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多