Why can I evaluate a function receiving a std::pair at compile-time, but not assert it? [duplicate]

依然范特西╮ 提交于 2021-02-11 14:13:59

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!