如何使用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
我写了一个函数接收可变数 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