Comments 6
Сталкивался с попдобным при использовании is_detected. Собственно интересная задача на тему ADL и правил инстанцирования шаблонов.
можно еще сделать вот так:
template<class T, auto Func = [] {}> concept boo = requires(T x) { f(x); Func(); };
и оно будет работать и не потребуется писать каждый раз новую чиселку
Чиселки я привёл лишь затем, чтобы явно показать разные воплощения шаблона.
На самом деле, противоядие от "the satisfaction result is different for identical atomic constraints" состоит в том, чтобы сделать ограничения не идентичными. Для этого и надо пропихнуть переменный параметр шаблона внутрь.
// всё ещё ill-formed-опасная версия
template<class T, int I> concept boo =
requires(T x) { f(x); } // одно атомарное ограничение
&& (I != 0); // другое атомарное ограничение (ну например)
// well-formed
template<class T, int I> concept boo =
requires(T x) { f(x); I; }; // одно большое атомарное ограничение
Трюк с неявным уникальным параметром шаблона - а каждая лямбда уникальна - это дополнительный уровень. В первую очередь, чтобы не писать чиселки. Чтобы каждое воплощение шаблона было новым. Но в любом случае, придётся упоминать его внутри requires.
Но мне кажется, что это плохая практика для больших программ. Как минимум, это приведёт к размножению воплощений. Сведём с ума сперва компилятор, а затем линкер...
Разве что как тест на ill-formed (godbolt):
// основной концепт для работы
template<class T> concept boo =
requires(T x) { f(x); };
// проверочное значение "по месту" - уже не концепт, во избежание
template<class T, auto F = []{}> constexpr bool boo_checker =
requires(T x) { f(x); F(); };
.....
void g(boo auto x) {
static_assert(boo_checker<decltype(x)>);
}
void g(auto x) {
static_assert(!boo_checker<decltype(x)>);
}
Просто кланг кеширует значения концепта, а гцц каждый раз считает. Довольно очевидное поведение
В том и прикол, что гцц значение концепта (булевой константы) кеширует в лучшем виде.
В вот значение атомарного ограничения (но только для данного концепта) он иногда пересчитывает, а иногда кеширует. Переход с false на true он диагностирует, а в обратную сторону - не догадался. Надо будет им зарепортить, уж больно смешной недочёт. Они не предполагали, что ограничение может откатываться.
Есть разные способы откатить ограничение вида `requires{ f(x); }`.
явно запретить наилучшую сигнатуру, `= delete`
добавить конкурирующие сигнатуры, чтобы нельзя было выбрать наилучшую
какой-то ещё способ я случайно нашёл, когда писал статью, но сейчас что-то не могу вспомнить
Концептуальный wish-you-happy-debug