static_assert 中的 std::pow 触发错误 C2057?

Posted

技术标签:

【中文标题】static_assert 中的 std::pow 触发错误 C2057?【英文标题】:std::pow in static_assert triggers error C2057? 【发布时间】:2014-05-01 01:55:24 【问题描述】:

Visual Studio 2013 中的以下代码导致错误 C2057:

#include <cmath>

int main() 
    static_assert(std::pow(2, 2) < 5, "foobar");
    return 0;

错误 C2057:预期的常量表达式

如果我在 GCC -std=c++0x 下编译它可以正常工作。 http://ideone.com/2c4dj5

如果我将std::pow(2, 2) 替换为4,它也会在Visual Studio 2013 下编译。

这是 VS2013 的错误吗? 我该如何解决这个问题?

【问题讨论】:

Visual C++ 2013 不支持constexpr。但即使是这样,pow 也不需要是constexpr,因此您的代码充其量是不可移植的,并且依赖于实现扩展。 【参考方案1】:

std::pow 不是constexpr 函数。 GCC 接受您的代码的原因是因为它提供了 pow 的 builtin version,它在编译时评估函数,因为参数是已知的。如果您将-fno-builtin 标志添加到GCC 命令行,您的代码fails to compile。报错信息如预期:

错误:静态断言的非常量条件

所以,这不是 VS2013 的 bug,而是 GCC 优化的效果。 clang doesn't compile 代码。

【讨论】:

【参考方案2】:

解决方法是将您自己的pow 实现为 constexpr 函数。

template<typename T>
constexpr T _pow(T x, size_t y) 
    return y ? x * _pow(x, y-1) : 1;

此实现非常简单,但应该适用于您的用例。

【讨论】:

以上是关于static_assert 中的 std::pow 触发错误 C2057?的主要内容,如果未能解决你的问题,请参考以下文章

标准对 std::pow、std::log 等 cmath 函数有啥看法?

c++11:为啥 std::forward 中的 static_assert 是必要的?

C++11 static_assert关键字

C++11 static_assert关键字

手把手写C++服务器(13):C++11新特性之静态断言static_assert

如何用宏做static_assert?