1. Действительно ли x(123)
вызывает operator()
функтора, который сгенерирован std::function
, который, в свою очередь, вызывает operator()
функтора, сгенерированного std::bind
, который в конечном итогезвонки func
?Оптимизируется ли это таким образом, чтобы он вызывал func(123)
?
Если у вас включена оптимизация, «вещи» будут встроены, и вы можете рассчитывать на то, что это будет оптимально, как и вызов func(123)
.
2. Где живет функтор, который генерирует std::bind
?В каком объеме?И как std::bind
назвать это?(могут быть конфликты имен)
Точное: bind
генерирует «мимолетное», определяемое реализацией, выражение связывания, которое может быть присвоено function<>
.Функция - это просто шаблон класса (спасибо, Люк Т.).И это живет в стандартной библиотеке.Однако выражения привязки определяются реализацией.
Стандартная библиотека содержит с признаками (std::is_bind_expression<>
), позволяющими MPL обнаруживать такие выражения.Одной из решающих особенностей выражений связывания над std :: function является то, что они (то, что я бы назвал) отложенные вызываемые объекты (т.е. они сохраняют полную семантику сайта вызова, включая возможность выбора перегрузок в реальном приложении).сайт).std::function<>
, с другой стороны, фиксирует один прототип и хранит вызываемый объект по типу стирания ( думаю variant
или any
).
3. Могут ли лямбды заменить все виды использования std :: bind?
4. Является ли std :: bind asоптимально, если вместо этого реализовать его как лямбду?
Лямбды AFAICT должны компилироваться примерно так же, как выражения bind.Одна вещь, которую я думаю лямбда не может сделать, что выражения связывания может это nested bind expressions
Edit В то время как специфические идиомы вложенных выражений связывания невозможно воспроизвести с помощью лямбд, лямбды, конечно, могут выражать (почти) то же самое гораздо естественнее:
bind(f, bind(g, _1))(x);
// vs.
[](int x) { f(g(x)); };
5. Что случилось с синтаксисом аргумента шаблона std::function
?Как это анализируется и как я могу использовать синтаксис этого аргумента шаблона в другом месте?
Это просто сигнатура функции ( тип функции), передаваемая в качестве параметра шаблона.
Вы также можете использовать его как тип параметра функции, который ухудшает до указателя функции (аналогично тому, как параметры массива по значениям ухудшаются до указателей, спасибо Дэвид!).На практике чаще всего где угодно, если вам не нужно имя переменная / тип:
void receiveFunction(void(int, double)); // spunky 'function<>'-style syntax
void sample(int, double) { }
int main()
{
receiveFunction(sample);
}
void receiveFunction(void (*f)(int, double)) // boring 'old' style syntax
// void ( f)(int, double) // ... also ok
{
// ..
}