Использование `std :: function ` для вызова не VOID-функции

StackOverflow https://stackoverflow.com/questions/9339829

Вопрос

Некоторое время назад я использовал std::function В значительной степени нравится это:

std::function<void(int)> func = [](int i) -> int { return i; };

По сути, я сделал это, потому что хотел хранить разные функциональные объекты в std::function, но я не хотел ограничивать типы возврата этих функций. Поскольку это, казалось, сработало, я пошел с этим. Но я не убежден, что его безопасно использовать, и я не смог найти никакой документации. Кто -нибудь знает, является ли это использование законным? Или, в целом, каковы правила для объекта, который можно безопасно назначить std::function?

Редактировать

Для разъяснения, проблема, с которой я обеспокоен, заключается в том, что функция Lambda возвращает int, пока func объявлен с типом возврата void. Анкет Я не уверен, что это нормально, особенно после вызова func() сделан.

Это было полезно?

Решение

Ваш код имеет неопределенное поведение. Это может работать или не работать так, как вы ожидаете. Причина, по которой он имеет неопределенное поведение, заключается в 20.8.11.2.1 [func.wrap.func.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 Из вызывшего объекта [1

§20.8.11.2.1/7:

template<class F> function(F f);

Требуется: F должен быть подлежащим конструктивным. f Должны быть вызовы (20.8.11.2) для типов аргументов argtypes и return type r.

Так ваш F Callable?

§20.8.11.2/2 говорит:

Обработанный объект F типа F является вызовом для типов аргументов ArgtyPes и возврата типа R, если выражение INVOKE (f, declval<ArgTypes>()..., R), рассматриваемый как необработанный операнд (пункт 5), хорошо образован (20.8.2).

И определение INVOKE говорит:

§20.8.2

  1. Определять INVOKE (f, t1, t2, ..., tN) следующим образом: ... материал, связанный с функцией члена/указателями VAR ... - f(t1, t2, ..., tN) во всех других случаях.

  2. Определять INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN) неявно преобразован в R.

И поскольку любой тип может быть неявно преобразован в void, ваш код должен быть в порядке с компилятором, соответствующим стандартам. Как указано в LITB ниже, нет неявного преобразования в пустоту, так что это не четко определен.

1]: Я думаю, что лямбда считается здесь вызываемым объектом, хотя у меня нет ссылки на это. Ваш лямбда также может быть использован в качестве указателя функции, поскольку он не фиксирует контекст

Похоже, это может быть нормально для анонимных функций.

Цитата от http://www.alorelang.org/release/0.5/doc/std_function.html (Это не из стандартной библиотеки C ++, однако похоже, что они используют что -то подобное в привязках до C ++)

Функциональные объекты могут быть созданы только с определением функции, выражением анонимной функции или путем доступа к связанному методу с использованием оператора Dot (.).

Другой способ, которым это можно было сделать, - это хранение указателя функций в автоматическом виде, как видно здесь: http://en.wikipedia.org/wiki/anonymous_function (Раздел C ++)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top