Использование "std:: function" для вызова функции Non-void
некоторое время назад я использовал std::function примерно так:
std::function<void(int)> func = [](int i) -> int { return i; };
в основном, я сделал это, потому что я хотел хранить различные объекты функции в std::function, но я не хотел ограничивать возвращаемые типы этих функций. Так как это, казалось, сработало, я пошел с ним. Но я не уверен, что он безопасен в использовании, и я не смог найти никакой документации по нему. Кто-нибудь знает, является ли это использование законным? Или, в более общем плане, каковы правила для объекта который можно безопасно назначить std::function?
редактировать
для уточнения, проблема, с которой я обеспокоен, заключается в том, что лямбда-функция возвращает int, а func объявляется с типом возврата void. Я не уверен, что это нормально, особенно после вызова func() сделано.
3 ответов
ваш код имеет неопределенное поведение. Это может сработать, а может и нет, как вы ожидаете. Почему это неопределенное поведение из-за 20.8.11.2.1 [Функ.упаковка.функция.con] / p7:
требуется:
Fдолжно бытьCopyConstructible.fдолжен вызываться (20.8.11.2) для типов аргументовArgTypesи возвращаемого типаR.
на f для вызова типа возврата R, f должен вернуть что-то неявно конвертируемое в возвращаемый тип std::function (void в вашем случае). И int неявно конвертируется в void.
я ожидал бы, что ваш код будет работать на большинстве реализаций. Однако по крайней мере на одной реализации (libc++), он не компилируется:
test.cpp:7:30: error: no viable conversion from 'int (int)' to 'std::function<void (int)>'
std::function<void(int)> ff = f;
^ ~
по иронии судьбы причина проистекает из еще один вопрос.
другой вопрос представлял проблему с std::function использование. Решение что проблема необходимости осуществления исполнения требуется: положение во время компиляции. Напротив, решение проблемы этого вопроса -запрещает реализация от применения требуется: предложения.
ваш случай использования хорошо определен в соответствии со стандартом.
вы строите std::function из callable объект[1]
§20.8.11.2.1/7:
template<class F> function(F f);требует: F должен быть CopyConstructible. f должен быть вызываемым (20.8.11.2) для типов аргументов ArgTypes и возвращение Р. типа
так ваш f вызываемый?
§20.8.11.2/2 говорит:
вызываемый объект f тип F вызывается для argtypes типов аргументов и верните тип R, если выражение
INVOKE (f, declval<ArgTypes>()..., R), рассматриваемый как недооцененный операнд (Пункт 5), хорошо сформирован (20.8.2).
и определение INVOKE говорит:
§20.8.2
определение
INVOKE (f, t1, t2, ..., tN)следующим образом: ... материал, касающийся указателей функций-членов/var ... -f(t1, t2, ..., tN)во всех остальных случаях.определение
INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN)неявно преобразовано вR.
и поскольку любой тип может быть неявно преобразован в как указано в litb ниже, нет неявного преобразования в void, поэтому это не очень хорошо определено.void, ваш код должен быть в порядке с компилятором, соответствующим стандартам.
[1]: я думаю, что лямбда считается вызываемым объектом здесь, хотя у меня нет ссылки на это. Ваша лямбда также может использоваться в качестве указателя функции не захватывает контекст
похоже, что это может быть нормально для анонимных функций.
цитата из http://www.alorelang.org/release/0.5/doc/std_function.html (это не из стандартной библиотеки C++, однако похоже, что они используют что-то подобное в привязках к C++)
объекты функции могут быть созданы только с определением функции, анонимным выражением функции или путем доступа к связанному методу с помощью точки (.) оператор.
другой способ сделать это - сохранить указатель функции в auto, как показано здесь:http://en.wikipedia.org/wiki/Anonymous_function (раздел C++)