Информация об изменениях

Сообщение Re[4]: хочуфичу - функции-конструкторы от 27.12.2023 23:14

Изменено 27.12.2023 23:15 Кодт

Re[4]: хочуфичу - функции-конструкторы
Здравствуйте, reversecode, Вы писали:

R>вроде стандарт вроде как не регламентирует концепты на аргументы итд

R>это воля разработчиков либ

R>если да

R>то это и через пропозл не протянуть

Сейчас действует такая логика:
вносить изменения в namespace std нельзя
— набор перегрузок make_unique / make_shared / optional::optional прибит гвоздями
— поэтому неудача подстановки — это в любом случае ошибка компиляции

А уж как именно эту ошибку формировать — дело десятое:
— отлуп на уровне объявления через старый добрый шаблонный sfinae
— отлуп на уровне объявления через requires
— static_assert на очень ранней стадии
— ошибка в недрах

Для пропозала здесь ещё нет места, потому что принцип замороженности std — достаточно важен.

Но вот сформулировать пропозал "давайте сделаем человекочитаемую диагностику"... было бы круто.
gcc ведь смог, при условии, что ему никто не мешает (хотя его собственная реализация стандартной библиотеки — мешает).


Ещё одно направление для пропозала... Не знаю, как точно сформулировать.
Суть вот в чём. Шаблон декоратора стирает то, как объявлены аргументы в декорируемой функции. И это может повлиять на правила выбора перегрузки.
Грубо говоря,
void f(X, Y, Z);
void f(X, Y, auto);
void f(X, auto, T) requires true;  // констрейны - это тоже часть сигнатуры (хотя в ABI и не проросло ещё?)

// и декоратор
void g(auto... a) /* [[signature_like (f(a...))]] */ ;
void g(X, U, V);

Без вытаскивания перегрузок — тут сработает очень тупое правило:
— если типы аргументов не совпадают с точностью до cv& с X,U,V — то лучше подходит шаблон
— а в рамках этого шаблона могут быть и неоднозначности, и наоборот, ничего не подойдёт

То есть, вместо плоского семейства перегрузок мы получаем иерархическое. И логика из-за этого меняется.

Вроде бы в прошлом или позапрошлом году я уже развлекался с темой "как делать полиморфную функцию, диспетчеризующую россыпь лямбд".
Есть такой лайфхак (прикроем глаза на то, что типы должны различаться — это легко сделать, но обвязка будет громоздкой)
template<class... Fs> struct joined : Fs... {
  Fs... fs_;
  joined(Fs... fs) : Fs(fs)... {}
  using F::operator();  // <-- ключевой момент
};

Тут мы говорим компилятору: "ну у тебя же есть сигнатуры всех операторов() у всех функциональных объектов, как-нибудь сам разрулишь"

А попробуйте подверстать аргумент, или, напротив, связать его? Ну положим, мы можем адаптировать каждую лямбду независимо
auto replace_first_with_int(auto f) {
  return [f](int x, auto... a) requires requires { f(x, a...); } { f(x, a...); };
}

и потом склеить эти адаптеры
auto join_replaced_first_with_int(auto... fs) {
  return join(replace_first_with_int(fs)...);
}

Вот только здесь мы прямо сразу обеспечили себе ошибку неоднозначности!
Если f1 и f2 подходят (например, у f1 тип аргумента идеально совпал, а у f2 через преобразование), то сигнатуры адаптеров — это (int, auto...) — и они подходят одинаково!

И в настоящее время я затрудняюсь сказать, как это можно красиво решить. И можно ли вообще.
Re[4]: хочуфичу - функции-конструкторы
Здравствуйте, reversecode, Вы писали:

R>вроде стандарт вроде как не регламентирует концепты на аргументы итд

R>это воля разработчиков либ

R>если да

R>то это и через пропозл не протянуть

Сейчас действует такая логика:
вносить изменения в namespace std нельзя
— набор перегрузок make_unique / make_shared / optional::optional прибит гвоздями
— поэтому неудача подстановки — это в любом случае ошибка компиляции

А уж как именно эту ошибку формировать — дело десятое:
— отлуп на уровне объявления через старый добрый шаблонный sfinae
— отлуп на уровне объявления через requires
— static_assert на очень ранней стадии
— ошибка в недрах

Для пропозала здесь ещё нет места, потому что принцип замороженности std — достаточно важен.

Но вот сформулировать пропозал "давайте сделаем человекочитаемую диагностику"... было бы круто.
gcc ведь смог, при условии, что ему никто не мешает (хотя его собственная реализация стандартной библиотеки — мешает).


Ещё одно направление для пропозала... Не знаю, как точно сформулировать.
Суть вот в чём. Шаблон декоратора стирает то, как объявлены аргументы в декорируемой функции. И это может повлиять на правила выбора перегрузки.
Грубо говоря,
void f(X, Y, Z);
void f(X, Y, auto);
void f(X, auto, T) requires true;  // констрейны - это тоже часть сигнатуры (хотя в ABI и не проросло ещё?)

// и декоратор
void g(auto... a) /* [[signature_like (f(a...))]] */ ;
void g(X, U, V);

Без вытаскивания перегрузок — тут сработает очень тупое правило:
— если типы аргументов не совпадают с точностью до cv& с X,U,V — то лучше подходит шаблон
— а в рамках этого шаблона могут быть и неоднозначности, и наоборот, ничего не подойдёт

То есть, вместо плоского семейства перегрузок мы получаем иерархическое. И логика из-за этого меняется.

Вроде бы в прошлом или позапрошлом году я уже развлекался с темой "как делать полиморфную функцию, диспетчеризующую россыпь лямбд".
Есть такой лайфхак (прикроем глаза на то, что типы должны различаться — это легко сделать, но обвязка будет громоздкой)
template<class... Fs> struct join : Fs... {
  Fs... fs_;
  joined(Fs... fs) : Fs(fs)... {}
  using F::operator();  // <-- ключевой момент
};

Тут мы говорим компилятору: "ну у тебя же есть сигнатуры всех операторов() у всех функциональных объектов, как-нибудь сам разрулишь"

А попробуйте подверстать аргумент, или, напротив, связать его? Ну положим, мы можем адаптировать каждую лямбду независимо
auto replace_first_with_int(auto f) {
  return [f](int x, auto... a) requires requires { f(x, a...); } { f(x, a...); };
}

и потом склеить эти адаптеры
auto join_replaced_first_with_int(auto... fs) {
  return join(replace_first_with_int(fs)...);
}

Вот только здесь мы прямо сразу обеспечили себе ошибку неоднозначности!
Если f1 и f2 подходят (например, у f1 тип аргумента идеально совпал, а у f2 через преобразование), то сигнатуры адаптеров — это (int, auto...) — и они подходят одинаково!

И в настоящее время я затрудняюсь сказать, как это можно красиво решить. И можно ли вообще.