【问题标题】:How to use std::enable_if_t with perfect forwarding?如何使用 std::enable_if_t 进行完美转发?
【发布时间】:2020-06-07 08:30:15
【问题描述】:

我写了一个函数,它接收一个可变数的 std::pairs,它从每对的第一个元素中减去第二个元素,并从新生成的结果中返回一个元组,如下所示:

template<typename... pairs, std::enable_if_t<((std::is_same_v<std::pair<int, int>, pairs>) && ...)>* = nullptr>
inline constexpr auto foo(pairs&& ...p) noexcept {
    return std::tuple((std::get<1>(std::forward<pairs>(p)) - std::get<0>(std::forward<pairs>(p)))  ...);
}

int main() {
    constexpr auto bar = foo(std::pair(4, 6), std::pair(3, 7), std::pair(1, 2));

    return 0;
}

这工作得很好。除非我尝试向它传递一个不是右值的 std::pair,像这样:

int main() {
    constexpr auto tup = std::pair(4, 6);
    constexpr auto bar = foo(tup, std::pair(3, 7), std::pair(1, 2));

    return 0;
}

如果我尝试这样做,我会收到以下错误:

no matching function for call to 'foo(const std::pair<int, int>&, std::pair<int, int>, std::pair<int, int>)'

如何将 std::pairs 作为左值和右值引用传递给该函数?我正在使用 C++17

【问题讨论】:

  • 我不确定,但问题可能出在std::same_v&lt;std::pair&lt;int,int&gt;, pair&gt; - 如果它是std::pair&lt;int,int&gt;&amp; 怎么办?此外,这不是编写此类代码的好方法。最好让它成为一个接受std::initializer_list&lt;std::pair&lt;int,int&gt;&gt;而不是模板混乱的非模板函数。

标签: c++ algorithm templates c++17 metaprogramming


【解决方案1】:

当你传递左值时,pairs 将在其类型中保持引用,所以

std::is_same_v<std::pair<int, int>, pairs>

结果为假。

您必须放弃引用,例如使用std::decay_t:

std::enable_if_t<((std::is_same_v<std::pair<int, int>, std::decay_t<pairs> >) && ...)>* = nullptr

【讨论】:

    【解决方案2】:

    当你将一个左值传递给函数时,由于转发引用 工作。您可以在检查之前使用std::decay_t 删除所有引用和cv-qualifiers:

    std::enable_if_t<((std::is_same_v<std::pair<int, int>, std::decay_t<pairs>>) && ...)>
    

    【讨论】:

      猜你喜欢
      • 2020-10-23
      • 2015-09-07
      • 2015-04-11
      • 1970-01-01
      • 2014-01-04
      • 2012-06-23
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多