https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84684
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> --- #include <array> #include <algorithm> template <typename alphabet_type> constexpr char to_char(alphabet_type const alph) { return alph.to_char(); } constexpr const char *check[][3] = { { "ACGT", __null, __null }, { "ACGT", "-", __null }, { "ACGT", "-", "ACGTN" }, { "ACGTN", "-", "ACGT" }, { "-", "ACGT", "ACGTN" } }; template <int idx, typename ...alphabet_types> struct union_composition { static constexpr size_t value_size = (alphabet_types::value_size + ... ); uint8_t _value; template <size_t fixed_size, typename alphabet_t> static constexpr auto value_to_char_helper(alphabet_t alphabet) { std::array<char, fixed_size> value_to_char{}; for (size_t i = 0u; i < alphabet_t::value_size; ++i) { value_to_char[i] = to_char(alphabet.assign_rank(i)); } return value_to_char; } static constexpr auto make_value_to_char() { constexpr auto N = sizeof...(alphabet_types); constexpr std::array<size_t, N> alphabet_sizes { alphabet_types::value_size... }; constexpr size_t fixed_size = std::max({alphabet_types::value_size...}); constexpr std::array value_to_char_tables = std::array<std::array<char, fixed_size>, N> { value_to_char_helper<fixed_size>(alphabet_types{})... }; std::array<char, value_size> value_to_char{}; static_assert (value_size == (idx == 0 ? 4 : (idx < 2 ? 5 : 10))); static_assert (N == (idx == 0 ? 1 : (idx < 2 ? 2 : 3))); static_assert (fixed_size == (idx < 2 ? 4 : 5)); static_assert (alphabet_sizes[0] == __builtin_strlen(check[idx][0])); if constexpr(idx >= 1) static_assert (alphabet_sizes[1] == __builtin_strlen(check[idx][1])); if constexpr (idx >= 2) static_assert (alphabet_sizes[2] == __builtin_strlen(check[idx][2])); static_assert (value_to_char_tables[0][0] == check[idx][0][0]); if constexpr (alphabet_sizes[0] > 1) static_assert (value_to_char_tables[0][1] == check[idx][0][1]); if constexpr (alphabet_sizes[0] > 2) static_assert (value_to_char_tables[0][2] == check[idx][0][2]); if constexpr (alphabet_sizes[0] > 3) static_assert (value_to_char_tables[0][3] == check[idx][0][3]); if constexpr (alphabet_sizes[0] > 4) static_assert (value_to_char_tables[0][4] == check[idx][0][4]); if constexpr (idx >= 1) { static_assert (value_to_char_tables[1][0] == check[idx][1][0]); if constexpr (alphabet_sizes[1] > 1) static_assert (value_to_char_tables[1][1] == check[idx][1][1]); if constexpr (alphabet_sizes[1] > 2) static_assert (value_to_char_tables[1][2] == check[idx][1][2]); if constexpr (alphabet_sizes[1] > 3) static_assert (value_to_char_tables[1][3] == check[idx][1][3]); if constexpr (alphabet_sizes[1] > 4) static_assert (value_to_char_tables[1][4] == check[idx][1][4]); } if constexpr (idx >= 2) { static_assert (value_to_char_tables[2][0] == check[idx][2][0]); if constexpr (alphabet_sizes[2] > 1) static_assert (value_to_char_tables[2][1] == check[idx][2][1]); if constexpr (alphabet_sizes[2] > 2) static_assert (value_to_char_tables[2][2] == check[idx][2][2]); if constexpr (alphabet_sizes[2] > 3) static_assert (value_to_char_tables[2][3] == check[idx][2][3]); if constexpr (alphabet_sizes[2] > 4) static_assert (value_to_char_tables[2][4] == check[idx][2][4]); } for (size_t i = 0u, value = 0u; i < N; ++i) for (size_t k = 0u; k < alphabet_sizes[i]; ++k, ++value) value_to_char[value] = value_to_char_tables[i][k]; return value_to_char; } }; struct gap { constexpr char to_char() const noexcept { return '-'; } constexpr gap & assign_rank([[maybe_unused]] bool const i) noexcept { return *this; } static constexpr size_t value_size{1}; }; struct dna4 { constexpr char to_char() const noexcept { return value_to_char[_value]; } constexpr dna4 & assign_rank(uint8_t const c) { _value = c; return *this; } static constexpr size_t value_size{4}; static constexpr char value_to_char[value_size] { 'A', 'C', 'G', 'T' }; uint8_t _value; }; struct dna5 { constexpr char to_char() const noexcept { return value_to_char[_value]; } constexpr dna5 & assign_rank(uint8_t const c) { _value = c; return *this; } static constexpr size_t value_size{5}; static constexpr char value_to_char[value_size] { 'A', 'C', 'G', 'T', 'N' }; uint8_t _value; }; constexpr std::array value_to_char1 = union_composition<0, dna4>::make_value_to_char(); static_assert(value_to_char1.size() == 4u); static_assert(value_to_char1[0] == 'A'); static_assert(value_to_char1[1] == 'C'); static_assert(value_to_char1[2] == 'G'); static_assert(value_to_char1[3] == 'T'); constexpr std::array value_to_char2 = union_composition<1, dna4, gap>::make_value_to_char(); static_assert(value_to_char2.size() == 5u); static_assert(value_to_char2[0] == 'A'); static_assert(value_to_char2[1] == 'C'); static_assert(value_to_char2[2] == 'G'); static_assert(value_to_char2[3] == 'T'); static_assert(value_to_char2[4] == '-'); constexpr std::array value_to_char3 = union_composition<2, dna4, gap, dna5>::make_value_to_char(); static_assert(value_to_char3.size() == 10u); static_assert(value_to_char3[0] == 'A'); static_assert(value_to_char3[1] == 'C'); static_assert(value_to_char3[2] == 'G'); static_assert(value_to_char3[3] == 'T'); static_assert(value_to_char3[4] == '-'); static_assert(value_to_char3[5] == 'A'); static_assert(value_to_char3[6] == 'C'); static_assert(value_to_char3[7] == 'G'); static_assert(value_to_char3[8] == 'T'); static_assert(value_to_char3[9] == 'N'); constexpr std::array value_to_char4 = union_composition<3, dna5, gap, dna4>::make_value_to_char(); static_assert(value_to_char4.size() == 10u); static_assert(value_to_char4[0] == 'A'); static_assert(value_to_char4[1] == 'C'); static_assert(value_to_char4[2] == 'G'); static_assert(value_to_char4[3] == 'T'); static_assert(value_to_char4[4] == 'N'); static_assert(value_to_char4[5] == '-'); static_assert(value_to_char4[6] == 'A'); static_assert(value_to_char4[7] == 'C'); static_assert(value_to_char4[8] == 'G'); static_assert(value_to_char4[9] == 'T'); constexpr std::array value_to_char5 = union_composition<4, gap, dna4, dna5>::make_value_to_char(); static_assert(value_to_char5.size() == 10u); static_assert(value_to_char5[0] == '-'); static_assert(value_to_char5[1] == 'A'); static_assert(value_to_char5[2] == 'C'); static_assert(value_to_char5[3] == 'G'); static_assert(value_to_char5[4] == 'T'); static_assert(value_to_char5[5] == 'A'); static_assert(value_to_char5[6] == 'C'); static_assert(value_to_char5[7] == 'G'); static_assert(value_to_char5[8] == 'T'); static_assert(value_to_char5[9] == 'N'); when preprocessed with -E -std=c++17 with g++ 7.3.1 and compiled with -std=c++17 trunk gives: ./cc1plus -quiet -std=c++17 pr84684-6.ii pr84684-6.C: In instantiation of ‘static constexpr auto union_composition<idx, alphabet_types>::make_value_to_char() [with int idx = 0; alphabet_types = {dna4}]’: pr84684-6.C:152:67: required from here pr84684-6.C:64:43: error: static assertion failed static_assert (value_to_char_tables[0][2] == check[idx][0][2]); pr84684-6.C:156:33: error: static assertion failed static_assert(value_to_char1[2] == 'G');