Pull to refresh

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`

  • добавить конкурирующие сигнатуры, чтобы нельзя было выбрать наилучшую

  • какой-то ещё способ я случайно нашёл, когда писал статью, но сейчас что-то не могу вспомнить

Sign up to leave a comment.

Articles