Является ли состояние метапрограммирования неупорядоченным (пока)?

Одно из моих самых любимых / злых изобретений, с которыми я столкнулся, – это счетчик констебров , который также называется метаопрограммированием . Как упоминалось в сообщении, он кажется законным в C ++ 14, и мне интересно, что-то изменилось с C ++ 17?

Ниже приводится реализация, в основном основанная на публикации

template  struct flag { friend constexpr int adl_flag(flag); constexpr operator int() { return N; } }; template  struct write { friend constexpr int adl_flag(flag) { return N; } static constexpr int value = N; }; template <int N, int = adl_flag(flag{})> constexpr int read(int, flag, int R = read(0, flag{})) { return R; } template  constexpr int read(float, flag) { return N; } template  constexpr int counter(int R = write<read(0, flag{}) + N>::value) { return R; } 

И мы используем его как

 static_assert(counter() != counter(), "Your compiler is mad at you"); template struct S {}; static_assert(!std::is_same_v<S, S>, "This is ridiculous"); 

Это, кстати, прямо противоречит сохранению состояний в метапрограммировании С ++?

Это активная проблема CWG 2118 :

Определение функции друга в шаблоне, а затем ссылка на эту функцию позже предоставляет средство для захвата и получения состояния метапрограммирования. Этот метод является тайным и должен быть плохо сформирован.

Записки на совещании в мае 2015 года:

РГС согласилась с тем, что такие методы должны быть плохо сформированы, хотя механизм их запрещения еще не определен.

Это все еще актуальная проблема, по крайней мере пока ничего не изменится в C ++ 17. Хотя, когда такой механизм запрета определен, это может быть ретроактивно управляется как ДР.

Давайте будем гением компьютера.