The following code works and prints the intersection as expected. However, changing max_codepoint
from 0x4000 to 0x5000 and it stops working with the error:
ConsoleApplication1.cpp(149, 30): [C2131] expression did not evaluate to a constant
I tried to change the 0x4000 to 0x5000 (or, more accurately, 0xffff to get the full UTF-16 range) and expected it to work. Yet, it doesn't.
#include <array>
#include <print>
#include <vector>
using ImWchar = unsigned short;
consteval std::vector<ImWchar> ConstGetGlyphRangesLatin()
{
return {
0x0020, 0x00FF, // Basic Latin + Latin Supplement
};
}
consteval std::vector<ImWchar> ConstGetGlyphRangesGW()
{
return {
0x20, 0x7f,
0xa1, 0xff,
0x100, 0x180,
0x0391, 0x0460,
0x2010, 0x266b,
0x3000, 0x3020,
0x3041, 0x3100,
0x3105, 0x312a,
0x3131, 0x318f,
0xac00, 0xd7a4,
0x4e00, 0x9fa6,
0xf900, 0xfa6b,
0xff01, 0xffe7
};
}
consteval bool in_range(const ImWchar c, const std::vector<ImWchar>& range)
{
for (size_t i = 0; i < range.size() - 1; i += 2) {
if (c >= range[i] && c <= range[i + 1]) return true;
}
return false;
};
consteval std::vector<ImWchar> find_glyph_range_intersection(const std::vector<ImWchar>& range1, const std::vector<ImWchar>& range2)
{
if (range1.empty() || range2.empty()) return {};
std::vector<ImWchar> intersection;
wchar_t start = 0;
bool in_intersection = false;
constexpr auto max_codepoint = 0x4000;
for (ImWchar c = 0; c <= max_codepoint; ++c) {
const bool in_both = in_range(c, range1) && in_range(c, range2);
if (in_both && !in_intersection) {
start = c;
in_intersection = true;
}
else if (!in_both && in_intersection) {
intersection.push_back(start);
intersection.push_back(c - 1);
in_intersection = false;
}
}
if (in_intersection) {
intersection.push_back(start);
intersection.push_back(max_codepoint);
}
intersection.push_back(0); // Null-terminate the range
return intersection;
}
template <typename T, size_t N>
consteval std::array<T, N> vec_to_array(const std::vector<T>& vec)
{
std::array<T, N> arr = {};
std::copy(vec.begin(), vec.end(), arr.begin());
return arr;
}
consteval auto get_intersection_array()
{
const auto latin = ConstGetGlyphRangesLatin();
const auto gw = ConstGetGlyphRangesGW();
const auto intersect = find_glyph_range_intersection(latin, gw);
return vec_to_array<ImWchar, 1'000>(intersect);
}
int main()
{
constexpr std::array arr = get_intersection_array();
for (auto c : arr) {
if (c != 0)
std::print("{}, ", c);
}
}
An expression is not a constant expression if evaluating it would require more evaluation steps than some implementation-defined limit.
That's to make sure that compilers aren't forced to work forever during compilation. Because of the halting problem it would otherwise be undecidable whether an expression is a constant expression.
Compilers usually have an option with which this implementation-defined limit can be increased, trading for compilation time.
As mentioned in a comment by @DubbleClick under this answer: The setting for MSVC seems to be /constexpr:steps
.