如何使用std::enable_if_t完美转发?

How to use std::enable_if_t with perfect forwarding?

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

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

当您将 lvalue 传递给函数时,它在参数包中的相应类型被推断为 lvalue 引用 由于如何转发引用 工作。您可以在检查之前使用 std::decay_t 删除所有引用和 cv-qualifiers

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

当您传递左值时,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