问题
I wrote a function that receives a variadic number of std::pairs. It takes the pairs, subtracts the 2nd element against the 1st element of each pair, and returns a tuple of the newly generated values like this:
#include <tuple>
#include <utility>
template<typename... pairs>
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 x = foo(std::pair(1, 2), std::pair(3, 7), std::pair(6, 7), std::pair(4, 8));
static_assert(std::get<0>(x) == 1);
return 0;
}
This works perfectly fine. However, if I want to add an assert to the top of the function foo
to check that the result of each subtraction is greater than or equal to 0 as:
template<typename... pairs>
inline constexpr auto foo(pairs&& ...p) noexcept {
static_assert(((std::get<1>(std::forward<pairs>(p)) - std::get<0>(std::forward<pairs>(p)) >= 0) && ...));
return std::tuple((std::get<1>(std::forward<pairs>(p)) - std::get<0>(std::forward<pairs>(p))) ...);
}
I get an error message saying:
error: non-constant condition for static assertion
My guess is that I can't use a static assert here because my function can be a constexpr, but it might evaluate at runtime depending on the parameters that I pass to it (I might pass it a std::pair that isn't a constexpr). Is my assumption correct? How can I pass it a std::pair and still be able to assert it?
I'm using C++17, and I'm trying to support GCC and msvc.
NOTE: I tried using a single std::pair, but that didn't work either. Also, I need the function to work with a std::pair of two ints only!
EDIT:
I wrote another function, and compiled it with std=c++2a
, and this works perfectly fine:
#include <utility>
#include <tuple>
template<std::pair<int, int> ...pairs>
inline constexpr auto foo() noexcept {
static_assert(((std::get<1>(pairs) - std::get<0>(pairs) >= 0) && ...));
return std::tuple((std::get<1>(pairs) - std::get<0>(pairs)) ...);
}
int main() {
constexpr auto x = foo<std::pair(1, 2), std::pair(3, 7), std::pair(6, 7), std::pair(4, 8)>();
static_assert(std::get<0>(x) == 1);
return 0;
}
I'm sure there must be a way around this in C++17?
来源:https://stackoverflow.com/questions/60363112/why-can-i-evaluate-a-function-receiving-a-stdpair-at-compile-time-but-not-ass