Что касается причины этого различия в типах указателей, то он был рассмотрен на SO несколько раз, например. здесь.
Цитата о том, что S.T.L. сказал:
Очень удивительно, что "gotcha" я бы сказал, что для std::function
требуются объекты функции CopyConstructible, и это довольно необычно в STL.
Обычно STL ленив в том смысле, что ему не нужны вещи впереди: если у меня есть что-то вроде std::list
типа T
, T
не нужно быть менее чем сопоставимым; только если вы вызываете функцию-член list<T>::sort
, тогда она действительно должна быть менее чем сопоставимой.
Правило основного языка, которое дает этому полномочия, заключается в том, что определения функций-членов шаблона класса не создаются, пока они на самом деле не нужны, и тела не существуют в каком-то смысле, пока вы на самом деле не назовете это.
Это обычно классно - это означает, что вы платите только за то, что вам нужно, но std::function
является особенным из-за стирания типа, потому что, когда вы создаете std::function
из некоторого вызываемого объекта F
, ему нужно сгенерировать все, что вы может потребоваться от этого объекта F
, потому что он собирается стереть его тип. Он требует всех операций, которые он может когда-либо понадобиться, независимо от того, используются ли они.
Итак, если вы построите std::function
из некоторого вызываемого объекта F
, F
абсолютно необходимо во время компиляции быть CopyConstructible. Это верно, хотя F
будет перемещен в std::function
, поэтому, даже если вы дадите ему значение r, и даже если вы никогда не копируете std::function
в любом месте вашей программы, F
по-прежнему требуется для CopyConstructible.
Вы получите сообщение об ошибке компилятора - возможно, ужасно, может быть, приятно - в зависимости от того, что вы получаете.
Он просто не может хранить движимые объекты только функции. Это ограничение конструкции, вызванное тем, что std::function
возвращается к boost/TR1, перед ссылками r-value, и в некотором смысле он никогда не может быть исправлен с помощью интерфейса std::function
, поскольку он стоит.
Исследуются альтернативы, возможно, у нас может быть другая "подвижная функция", поэтому мы, скорее всего, получим какую-то оболочку с тиснением, которая может хранить подвижную функцию только в будущем, но std::function
, поскольку она стоит в С++ 17 прямо сейчас не может этого сделать, поэтому просто будьте в курсе.