在 Visual Studio 中解决忽略的 constexpr?

Work around disregarded constexpr in Visual Studio?

我有这个代码:

constexpr int log2(const unsigned int x) {
    return x < 4 ? 1 : 1 + log2(x / 2);
}

int main() {
    bitset<log2(2)> foo;
    int bar[log2(8)];

    cout << log2(8) << endl;
}

这在 gcc 中工作正常:https://ideone.com/KooxoS

但是当我尝试 时,出现了这些错误:

error C2975: _Bits: invalid template argument for std::bitset, expected compile-time constant expression
note: see declaration of _Bits
error C2131: expression did not evaluate to a constant
note: failure was caused by call of undefined function or one not declared constexpr
note: see usage of log2

显然 log2constexpr 所以我认为这只是 中的一个错误。有什么办法可以解决这个错误吗?

Obviously log2 is constexpr

一个函数是 constexpr 并不意味着它总是可以用来计算一个 compute-time 值。当 x >= 4 时,您正在调用 std::log2,这不是 constexpr 本身。

GCC 将它们作为扩展来实现。参见 Is it a conforming compiler extension to treat non-constexpr standard library functions as constexpr?

您的项目似乎包含标准 std::log2 函数,编译器将其与您的 log2 函数混淆。即使您不 #include <cmath> 也会发生这种情况,因为允许标准 headers 包含任何其他标准 headers。这也是using namespace std;适得其反的另一个例子。

一个解决方案是将 constexpr 函数重命名为其他名称:

#include <bitset>
#include <iostream>

using namespace std;

constexpr int logTwo(const unsigned int x) {
    return x < 4 ? 1 : 1 + logTwo(x / 2);
}

int main() {
    bitset<logTwo(2)> foo;
    int bar[logTwo(8)];

    cout << logTwo(8) << endl;
}

Demo

编辑:在这种情况下,似乎 using namespace std; 可能无关。无论如何,标准 log2 函数可能在全局命名空间中可用。