#c #c 17 #std-function #c 23
Вопрос:
C 23 представил std::function
двоюродного std::move_only_function
брата , как и его название, это оболочка только для перемещения для вызываемых объектов, доступных только для перемещения (демо).:
#include <functional>
#include <memory>
int main() {
auto l = [p = std::make_unique<int>(0)] { };
std::function<void(void)> f1{std::move(l)}; // ill-formed
std::move_only_function<void(void)> f2{std::move(l)}; // well-formed
}
Но в отличие std::function
от этого , стандарт не определяет для него руководства по вычету (демонстрационное):
#include <functional>
int func(double) { return 0; }
int main() {
std::function f1{func}; // guide deduces function<int(double)>
std::move_only_function f2{func}; // deduction failed
}
Есть ли причина для запрета CTAD?
Комментарии:
1. Нет необходимости подозревать, голосование по CTAD уже состоялось open-std.org/jtc1/sc22/wg21/docs/papers/2021/… — 1 за против 9 против.
2. вы можете спросить авторов статьи, например, в Twitter @ CppSage и @ sempuki1 или по адресам электронной почты, указанным в статье
3. Сайт проводника компилятора называется Godbolt, а не Goldbot; он назван в честь Мэтта Годболта.
Ответ №1:
Подобные обертки для стирания типов move_only_function
предназначены для использования на границах API, где типы являются явными, что делает CTAD для них сомнительной полезностью.
Любой CTAD для этих вызываемых оболочек в любом случае должен быть довольно ограниченным — он не может обрабатывать перегруженные функции или шаблоны функций, что также означает, что он не может обрабатывать общие лямбды, что является довольно существенным ограничением его полезности. std::function
CTAD также поставляется с оговоркой о том, что более поздние стандарты могут изменить выводимый тип (мы его еще не изменили, но и не удалили оговорку).
И при move_only_function
этом выводятся не только типы возвращаемых данных и аргументов. const
, noexcept
, и ref-квалификаторы все в игре, и это создает новые проблемы с дизайном. Например, выводит ли вывод из int (*)(int)
вывода int(int)
? Почему бы и нет int(int) const
— указатели функций, в конце концов, можно вызывать постоянно?
И если CTAD окажется необходимым — и кто — то придумает для него хороший дизайн-его всегда можно добавить позже.
Я не знаю, все ли эти вопросы были затронуты в обсуждении LEWG (протоколы довольно скудны), но я думаю, что их более чем достаточно, чтобы оправдать отказ от поддержки CTAD.
Комментарии:
1.Если есть свободная функция
void foo()
, я думаюmove_only_function
, что ее можно вывестиvoid()
такstd::function
же, как и раньше, поскольку она явно интуитивно понятна. И мы все еще можем назначить его вызываемому объекту, у которого естьvoid operator()
илиvoid operator() const
. Когда вызываемый объект имеет иconst
const
то, и другое, и неквалифицированный оператор (), вызов последнего также кажется более интуитивным выбором, потому что мы выводим тип через свободную функцию. Если мы хотим позвонитьoperator() const
, мы должныvoid() const
явно указать в начале.2. Дело в том, что ответы не совсем очевидны (с другой стороны, делает
[]{}
выводvoid() const
?). Обычно для этого нужно было бы рассмотреть реальные варианты использования — за исключением того, что дляmove_only_function
CTAD существует не так много вариантов использования, с которых можно начать.3. «делает
[]{}
выводvoid() const
?» Абсолютно. Так же, как[] noexcept {}
и выводитсяvoid() const noexcept
. С введением вывода об этом ситуация будет становиться все более и более сложной, но я все еще с нетерпением жду того дня, когда CTAD будет восстановлен, хотя это кажется очень далеким. 😉