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?
StaticArray, as well as the whole implementation of the constructor.StaticArray, as well as the whole implementation of the constructor") in a comment. If it fits in a comment, it fits in a question, no?#include <memory> struct StaticArray { template <typename OA> constexpr StaticArray(OA&& otherArray) {} constexpr ~StaticArray() = default; }; // class StaticArray consteval void UnitTest() { size_t cppArray[] = { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 }; StaticArray sArr = std::move(cppArray); } static_assert((UnitTest(), true), "failed!");[[nodiscard]] constexpr T* allocate( std::size_t n ); (since C++20)