В чем вообще проблема NTTP параметров?
Рассмотрим простую функцию template <T value> void f();
До C++20 в качестве T мог выступать один из небольшого множества типов. Особенность этого множества состояла в том, что можно два объекта типа T
сравнить, убедиться в их эквивалентности. В частности, f<2>
и f<1+1>
оказывались одинаковыми инстанцированиями, так как 2==1+1. А ещё от них от всех можно посчитать хеш по алгоритму, выбранному компилятором.
Теперь допустим, что мы хотим сделать T
= std::string
(допустим также, что строка у нас уже вся обмазана constexpr). Как компилятору проверить, что f<std::string("1")>
и f<std::string("1")>
- это одна и та же функция? Логично, что для этого он должен уметь сравнивать в constexpr
строки. Более того, так как шаблоны кэшируются, то очень хорошо бы ещё уметь и хешировать такие параметры (хеш-таблица быстрее дерева). То есть при инстанцировании очередной f<some_string>
компилятор должен поискать среди уже проинстанцированных f<..>
такую же.
Это приводит к необходимости делать подобие constexpr hash + constexpr operator<=>, который должен быть написан автором типа T (std::string или какой-то used-defined). Здесь и засада. Пользователь может написать некорректную реализацию, что приведёт к UB при компиляции, которое невозможно диагностировать. Что просто сломает компилятор.
Поэтому решили сделать требования типа all public и прочее - компилятор считает такие типы просто последовательностью более примитивных типов, от которых он умеет считать хеш и сравнивать.
> Здесь и засада. Пользователь может написать некорректную реализацию, что приведёт к UB при компиляции, которое невозможно диагностировать. Что просто сломает компилятор.
Что то не пойму, UB в constexpr как раз диагностируются компилятором. В чём тут отличие от обычной constexpr foo функции?