aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/cpp1z/constexpr-84684.C
blob: 0e7912d406704b9ee4af211ee0c9fcb112b00dd0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// PR c++/84684
// { dg-options -std=c++17 }

typedef decltype (sizeof (0)) size_t;

namespace std {
  template<class _E>
  struct initializer_list
  {
    typedef _E value_type;
    typedef const _E& reference;
    typedef const _E& const_reference;
    typedef size_t size_type;
    typedef const _E* iterator;
    typedef const _E* const_iterator;
    iterator _M_array;
    size_type _M_len;
    constexpr initializer_list(const_iterator __a, size_type __l) : _M_array(__a), _M_len(__l) { }
    constexpr initializer_list() noexcept : _M_array(0), _M_len(0) { }
    constexpr size_type size() const noexcept { return _M_len; }
    constexpr const_iterator begin() const noexcept { return _M_array; }
    constexpr const_iterator end() const noexcept { return begin() + size(); }
  };
}

template <typename E, size_t N>
struct array
{
  constexpr E &operator[](size_t n) noexcept { return elems[n]; }
  constexpr const E &operator[](size_t n) const noexcept { return elems[n]; }
  constexpr size_t size() const { return N; }
  E elems[N];
};

template<typename T>
constexpr
inline T
max (std::initializer_list<T> i)
{
  const T *b = i.begin ();
  const T *e = i.end ();
  if (b == e) return *b;
  const T *r = b;
  while (++b != e)
  if (*r < *b)
    r = b;
  return *r;
}

template <typename alphabet_type>
constexpr char to_char(alphabet_type const alph)
{
  return alph.to_char();
}

template <typename ...alphabet_types>
struct union_composition
{
  static constexpr size_t value_size = (alphabet_types::value_size + ... );
  unsigned char _value;
  template <size_t fixed_size, typename alphabet_t>
  static constexpr auto value_to_char_helper(alphabet_t alphabet)
  {
    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 array<size_t, N> alphabet_sizes { alphabet_types::value_size... };
    constexpr size_t fixed_size = max({alphabet_types::value_size...});
    array value_to_char_tables = array<array<char, fixed_size>, N> {
      value_to_char_helper<fixed_size>(alphabet_types{})...
    };
    array<char, value_size> value_to_char{};
    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(unsigned char 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' };
  unsigned char _value;
};

struct dna5
{
  constexpr char to_char() const noexcept { return value_to_char[_value]; }
  constexpr dna5 & assign_rank(unsigned char 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' };
  unsigned char _value;
};

constexpr array value_to_char1 = union_composition<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 array value_to_char2 = union_composition<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 array value_to_char3 = union_composition<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 array value_to_char4 = union_composition<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 array value_to_char5 = union_composition<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');