Сообщение 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 ведь смог, при условии, что ему никто не мешает (хотя его собственная реализация стандартной библиотеки — мешает).
Ещё одно направление для пропозала... Не знаю, как точно сформулировать.
Суть вот в чём. Шаблон декоратора стирает то, как объявлены аргументы в декорируемой функции. И это может повлиять на правила выбора перегрузки.
Грубо говоря,
Без вытаскивания перегрузок — тут сработает очень тупое правило:
— если типы аргументов не совпадают с точностью до cv& с X,U,V — то лучше подходит шаблон
— а в рамках этого шаблона могут быть и неоднозначности, и наоборот, ничего не подойдёт
То есть, вместо плоского семейства перегрузок мы получаем иерархическое. И логика из-за этого меняется.
Вроде бы в прошлом или позапрошлом году я уже развлекался с темой "как делать полиморфную функцию, диспетчеризующую россыпь лямбд".
Есть такой лайфхак (прикроем глаза на то, что типы должны различаться — это легко сделать, но обвязка будет громоздкой)
Тут мы говорим компилятору: "ну у тебя же есть сигнатуры всех операторов() у всех функциональных объектов, как-нибудь сам разрулишь"
А попробуйте подверстать аргумент, или, напротив, связать его? Ну положим, мы можем адаптировать каждую лямбду независимо
и потом склеить эти адаптеры
Вот только здесь мы прямо сразу обеспечили себе ошибку неоднозначности!
Если f1 и f2 подходят (например, у f1 тип аргумента идеально совпал, а у f2 через преобразование), то сигнатуры адаптеров — это (int, auto...) — и они подходят одинаково!
И в настоящее время я затрудняюсь сказать, как это можно красиво решить. И можно ли вообще.
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 ведь смог, при условии, что ему никто не мешает (хотя его собственная реализация стандартной библиотеки — мешает).
Ещё одно направление для пропозала... Не знаю, как точно сформулировать.
Суть вот в чём. Шаблон декоратора стирает то, как объявлены аргументы в декорируемой функции. И это может повлиять на правила выбора перегрузки.
Грубо говоря,
Без вытаскивания перегрузок — тут сработает очень тупое правило:
— если типы аргументов не совпадают с точностью до cv& с X,U,V — то лучше подходит шаблон
— а в рамках этого шаблона могут быть и неоднозначности, и наоборот, ничего не подойдёт
То есть, вместо плоского семейства перегрузок мы получаем иерархическое. И логика из-за этого меняется.
Вроде бы в прошлом или позапрошлом году я уже развлекался с темой "как делать полиморфную функцию, диспетчеризующую россыпь лямбд".
Есть такой лайфхак (прикроем глаза на то, что типы должны различаться — это легко сделать, но обвязка будет громоздкой)
Тут мы говорим компилятору: "ну у тебя же есть сигнатуры всех операторов() у всех функциональных объектов, как-нибудь сам разрулишь"
А попробуйте подверстать аргумент, или, напротив, связать его? Ну положим, мы можем адаптировать каждую лямбду независимо
и потом склеить эти адаптеры
Вот только здесь мы прямо сразу обеспечили себе ошибку неоднозначности!
Если f1 и f2 подходят (например, у f1 тип аргумента идеально совпал, а у f2 через преобразование), то сигнатуры адаптеров — это (int, auto...) — и они подходят одинаково!
И в настоящее время я затрудняюсь сказать, как это можно красиво решить. И можно ли вообще.
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...) — и они подходят одинаково!
И в настоящее время я затрудняюсь сказать, как это можно красиво решить. И можно ли вообще.