BeigeAlert
BeigeAlert

Reputation: 313

MSVC constexpr error "a non-constant (sub-)expression was encountered (with no info) (works on Clang!)

While working on my own array types, I encountered this issue, where one of my unit tests passes for Clang, but fails on MSVC with the following messages:

error C7595: 'UnitTest': call to immediate function is not a constant expression  
note: a non-constant (sub-)expression was encountered  
note: the call stack of the evaluation (the oldest call first) is  
note: while evaluating function 'void UnitTest(void)'  

https://godbolt.org/z/KrbWMe8sM

Code is:

#include <exception>
#include <memory>

template <typename ElementType, size_t ElementCount>
class StaticArray
{

public:

    template <typename OA>
    constexpr StaticArray(OA&& otherArray)
        : m_cxBuffer(std::allocator<ElementType>().allocate(static_cast<size_t>(ElementCount)))
    {
        using OtherArrayType = decltype(otherArray);
        using OtherArrayTypeNoRef = std::remove_reference_t<OtherArrayType>;

        m_count = std::extent_v<OtherArrayTypeNoRef>;

        ElementType* src = otherArray;
        ElementType* srcEnd = src + m_count;
        ElementType* dst = m_cxBuffer;

        ElementType* srcCurrent = src;
        ElementType* dstCurrent = dst;
        while (srcCurrent != srcEnd)
        {
            std::construct_at(dstCurrent, std::move(*srcCurrent));
            ++srcCurrent;
            ++dstCurrent;
        }
    }

    constexpr ~StaticArray() noexcept
    {
        while (m_count > 0)
            std::destroy_at(m_cxBuffer + (--m_count));

        std::allocator<ElementType>().deallocate(m_cxBuffer, static_cast<size_t>(ElementCount));
    }

    size_t m_count = 0;
    ElementType* m_cxBuffer = nullptr;

}; // class StaticArray


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////


consteval void UnitTest()
{
    size_t cppArray[] = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 };
    StaticArray<size_t, 15> sArr = std::move(cppArray);  // line 54
}
static_assert((UnitTest(), true), "failed!");

Removing the std::move from line 54 makes it work correctly in this whittled-down example, but is not acceptable for the full version where I want to distinguish between moving and copying.

Is this a bug with MSVC, or is Clang incorrect in accepting this code?

Upvotes: 0

Views: 150

Answers (0)

Related Questions