0

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?

11
  • 11
    Thanks a lot for providing a link to Godbolt, but please embed everything needed to answer the question into the question's body itself. Links tend to expire. Commented May 18, 2024 at 23:55
  • 1
    Note that it's enough to remove all template parameters and fields from StaticArray, as well as the whole implementation of the constructor. Commented May 19, 2024 at 0:02
  • 1
    stackoverflow.com/questions/58466245/… Commented May 19, 2024 at 0:19
  • 2
    Let's see if I can fit the minimized example ("remove all template parameters and fields from 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!"); Commented May 19, 2024 at 2:10
  • 1
    @PepijnKramer The very page you link to says [[nodiscard]] constexpr T* allocate( std::size_t n ); (since C++20) Commented May 19, 2024 at 6:59

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.