C++ 为什么我可以在编译时对接收std::pair的函数求值,但不能断言它?

C++ 为什么我可以在编译时对接收std::pair的函数求值,但不能断言它?,c++,algorithm,templates,c++17,metaprogramming,C++,Algorithm,Templates,C++17,Metaprogramming,我编写了一个函数,它接收可变数量的std::pairs。它获取这些对,用每对的第一个元素减去第二个元素,并返回一个新生成值的元组,如下所示: #include <tuple> #include <utility> template<typename... pairs> inline constexpr auto foo(pairs&& ...p) noexcept { return std::tuple((std::get<1&

我编写了一个函数,它接收可变数量的std::pairs。它获取这些对,用每对的第一个元素减去第二个元素,并返回一个新生成值的元组,如下所示:

#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;
}
我收到一条错误消息,上面说:
错误:静态断言的非常量条件

我的猜测是,我不能在这里使用静态断言,因为我的函数可以是constexpr,但它可能在运行时根据我传递给它的参数进行计算(我可能会传递一个不是constexpr的std::pair)。我的假设正确吗?如何传递std::pair并仍然能够断言它

我正在使用C++17,并且我正在尝试支持GCC和msvc

注意: 我尝试使用单个std::pair,但也不起作用。此外,我还需要该函数仅用于两个int的std::pair

编辑:

我编写了另一个函数,并用
std=c++2a
编译了它,它工作得非常好:

#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;
}
#包括
#包括
模板
内联constexpr auto foo()noexcept{
静态_断言((std::get(pairs)-std::get(pairs)>=0&&……);
返回std::tuple((std::get(pairs)-std::get(pairs))…);
}
int main(){
constexpr auto x=foo();
静态断言(std::get(x)==1);
返回0;
}

我相信在C++17中一定有办法解决这个问题。

胶囊摘要是
static\u assert
需要
constexpr
表达式。在变量模板的上下文中,这有点困难…你的假设是正确的。它可能在C++20s
consteval
tho中工作,但不要引用我的话。@Timo:不,甚至没有。函数参数(目前)不是
constexpr
,因此不能在需要常量表达式的地方使用。是否有方法将该对作为模板参数传递?您可以检查条件并引发异常(或调用任何仅限运行时的函数),而不必使用模板参数。在编译时计算仅运行时表达式会导致编译器错误。请参阅(基本问题是相同的)。
#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;
}