Skip to content

<array>: Cannot use array<T,N> in constexpr context in comparison to T[N] in debug #1486

@Andersama

Description

@Andersama

Describe the bug
Cannot compile code when using ::std::array<T,N> over T[N] in a constexpr context. Issue stems from _STL_VERIFY macro in the array [] operator making a non constexpr call.

Example code

#include <iostream>
#include <array>
#include <cassert>

struct non_trivial_struct {
	constexpr non_trivial_struct() noexcept {};
};

struct construct_array {};

template<typename Ty, size_t N>
struct like_optional_but_an_array {
	union {
		::std::array<Ty, N> data; //gives an error about a non constexpr call
		//Ty data[N]; //no problem
		non_trivial_struct dummy;
	};

	constexpr like_optional_but_an_array() noexcept : dummy{} {};
	constexpr like_optional_but_an_array(construct_array) noexcept : data{} {};

	[[nodiscard]] constexpr Ty& operator[](size_t idx) noexcept {
		assert(idx < N);
		return data[idx];
	}
	[[nodiscard]] constexpr const Ty& operator[](size_t idx) const noexcept {
		assert(idx < N);
		return data[idx];
	}
};

constexpr auto something_at_compiletime() {
	like_optional_but_an_array<uint32_t, 8> compile_time_thing{ construct_array{} };
	return compile_time_thing[7ULL];
};

int main(void) {
	constexpr like_optional_but_an_array<uint32_t, 8> thing;
	constexpr auto test = something_at_compiletime();
	::std::cout << ((int)thing[3ULL]) << '\n';
	::std::cout << test << '\n';

	return 0;
}

Here's the current implementation.

    _NODISCARD _CONSTEXPR17 reference operator[](_In_range_(0, _Size - 1) size_type _Pos) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
        _STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0

        return _Elems[_Pos];
    }

    _NODISCARD constexpr const_reference operator[](_In_range_(0, _Size - 1) size_type _Pos) const noexcept
    /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
        _STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif // _CONTAINER_DEBUG_LEVEL > 0

        return _Elems[_Pos];
    }

Expected behavior
Should be able to compile the above code when using ::std::array<T,N> over T[N] in debug mode.

STL version
Microsoft Visual Studio Community 2019 Preview Version 16.8.0 Preview 3.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    invalidThis issue is incorrect or by design

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions