I have a class that wraps an array. It inherits from an abstract base class defining one virtual constexpr
method for the function-call operator. In the child class, I override said method and access the internal array:
#include <cstddef>
#include <array>
#include <initializer_list>
template <typename T, std::size_t N>
class ContainerBase {
public:
virtual constexpr const T& operator()(std::size_t i) const = 0;
};
template <typename T, std::size_t N>
class Container : public ContainerBase<T, N> {
public:
constexpr Container(std::initializer_list<T> data) {
std::copy(data.begin(), data.end(), _items.begin());
}
constexpr const T& operator()(std::size_t i) const override {
return _items[i];
}
private:
std::array<T, N> _items;
};
int main () {
constexpr Container<int, 3> C = {2, -91, 7};
constexpr int F = C(1);
static_assert(F == -91);
}
Here is the godbolt link.
To the best of my understanding, this is all legal code in C++20, which allows virtual constexpr
. G++ 10.3 and Clang 12 both accept this as valid code, however MSVC 19.33 does not accept it, claiming that variable F
is not a constant expression:
msvc_buggy_constexpr.cpp(29,21): error C2131: expression did not evaluate to a constant
msvc_buggy_constexpr.cpp(21,16): message : a non-constant (sub-)expression was encountered
msvc_buggy_constexpr.cpp(31,5): error C2131: expression did not evaluate to a constant
msvc_buggy_constexpr.cpp(21,16): message : a non-constant (sub-)expression was encountered
What gives? This looks like a compiler bug in MSVC to me. I would investigate further but MSVC on godbolt.org seems to be down right now.
I should add, the issue only presents itself when the function call operator method is virtual
—when it is not, the issue does not occur.
Can anyone advise?
User @Barry agrees with me that it's definitely a bug in MSVC.
I've submitted this bug report.
Hopefully the issue gets resolved soon.
Thanks all for your comments and further insights, it's very helpful!