Странное выражение "- > * [] " в исходном коде cpp на C++.библиотека реагировать
вот фрагмент кода C++, который я нашел в документации cpp.библиотека реакций:
auto in = D::MakeVar(0);
auto op1 = in ->* [] (int in)
{
int result = in /* Costly operation #1 */;
return result;
};
Я никогда не видел ->* []
нотации. Во-первых, я думал, что это просто опечатка, но я также нашел такое выражение в исходный код:
auto volume = (width,height,depth) ->* [] (int w, int h, int d) {
return w * h * d;
};
это действительно C++11 (или C++14)? Что это значит?
3 ответа:
единственный пример на связанной странице, где я вижу
->*
это:auto in = D::MakeVar(0); auto op1 = in ->* [] (int in) { int result = in /* Costly operation #1 */; return result; }; auto op2 = in ->* [] (int in) { int result = in /* Costly operation #2 */; return result; };
вот мое предположение-любой тип возвращается
D::MakeVar()
перегружает оператор указателя на член->*
, и вторым аргументом для этого перегруженного оператора является объект функции, т. е. лямбда-выражение.Что касается этого примера:
auto volume = (width,height,depth) ->* [] (int w, int h, int d) { return w * h * d; };
Я предполагаю, какие типы
width
,height
&depth
are, перегрузка оператора запятой, и результат дает тот же тип, чтоMakeVar
дает, или другой тип, что перегрузки->*
. Остальное-то же самое, что и в первом примере.
@ответ Преториана является правильным. этой - это код из cpp.реагировать
/////////////////////////////////////////////////////////////////////////////////////////////////// /// operator->* overload to connect inputs to a function and return the resulting node. /////////////////////////////////////////////////////////////////////////////////////////////////// // Single input template < typename D, typename F, template <typename D_, typename V_> class TSignal, typename TValue, class = std::enable_if< IsSignal<TSignal<D,TValue>>::value>::type > auto operator->*(const TSignal<D,TValue>& inputNode, F&& func) -> Signal<D, typename std::result_of<F(TValue)>::type> { return D::MakeSignal(std::forward<F>(func), inputNode); } // Multiple inputs template < typename D, typename F, typename ... TSignals > auto operator->*(const InputPack<D,TSignals ...>& inputPack, F&& func) -> Signal<D, typename std::result_of<F(TSignals ...)>::type> { return apply( REACT_IMPL::ApplyHelper<D, F&&, TSignals ...>::MakeSignal, std::tuple_cat(std::forward_as_tuple(std::forward<F>(func)), inputPack.Data)); }
/////////////////////////////////////////////////////////////////////////////////////////////////// /// Comma operator overload to create input pack from 2 signals. /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename TLeftVal, typename TRightVal > auto operator,(const Signal<D,TLeftVal>& a, const Signal<D,TRightVal>& b) -> InputPack<D,TLeftVal, TRightVal> { return InputPack<D, TLeftVal, TRightVal>(a, b); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Comma operator overload to append node to existing input pack. /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename ... TCurValues, typename TAppendValue > auto operator,(const InputPack<D, TCurValues ...>& cur, const Signal<D,TAppendValue>& append) -> InputPack<D,TCurValues ... , TAppendValue> { return InputPack<D, TCurValues ... , TAppendValue>(cur, append); }
как вы можете видеть перегруженные функции
operator->*
который принимает сигнал (D::MakeVar(0)
) и функтор (лямбда)и свободная функция
operator,
, который принимает два сигнала
(автор)
во-первых, преторианцы отвечают правильно, но я хотел бы немного уточнить.
обратите внимание, что эта библиотека все еще очень экспериментальная, и я все еще работаю над документацией. Текущее состояние указанной документации можно найти в wiki, в частности https://github.com/schlangster/cpp.react/wiki/User-Guide-%7C-Signals связано с вопросом.
вот более подробный пример:
int calcVolume(int w, int h, int d) { return w*h*d; } D::VarSignalT<int> width = D::MakeVar(1); D::VarSignalT<int> height = D::MakeVar(2); D::VarSignalT<int> depth = D::MakeVar(3); D::SignalT<int> volume = MakeSignal(&calcVolume, width, height, depth); Observe(volume, [] (int v) { printf("volume changed to %d\n", v); }); width.Set(10); // => volume changed to 60. printf("volume: %d\n", volume.Value()); // short: volume()
это своего рода привязка (сигналы привязки как вход функции), но это не то же самое, что обратный std::bind. объем не является объектом function. В частности, объем не пересчитывается при вызове Value (), он пересчитывается при изменении одного из его зависимых сигналов, результат сохраняется, а Value () возвращает его. Таким образом, это по существу push - распространение изменений с некоторыми дополнительными функциями (без избыточных обновлений, без сбоев, необязательных неявных распараллеливание.)
проблема в том, что MakeSignal запутывается при смешивании с временными сигналами и лямбдами:
// First create a temporary area signal, then use it as an argument for the volume signal D::SignalT<int> volume = MakeSignal( [] (int a, int d) { return a * d; }, MakeSignal( [] (int w, int h) { return w * h; }, width, height), depth);
никто не хочет читать подобное, верно? По крайней мере, я не хочу.
таким образом, есть альтернативный синтаксис, который перемещает зависимости влево, обернутый SignalList.
// Note: Not sure if I have already pushed this variant yet D::SignalT<int> volume = MakeSignalList( MakeSignalList(width, height).Bind([] (int w, int h) { return w * h; }), depth ).Bind([] (int a, int d) { return a * d; });
и, наконец, со злой запятой и - > * перегружает:
D::SignalT<int> volume = ( (width, height) ->* [] (int w, int h) { return w * h; }, depth ) ->* [] (int area, int d) { return a * d; };
проблема с этим, как уже отмечалось, является что любой, кто видит его в первый раз, не знает, что, черт возьми, происходит.
С другой стороны, подключение сигналов к функциям должно быть очень распространенной задачей при использовании этой библиотеки. Как только вы знаете, что он делает, версия ->* более лаконична и визуализирует график потока данных (ребра от ширины и высоты до временной области, ребра от области и глубины до объема).