Phi*_*ßen 55 c++ language-lawyer c++11 operator-arrow-star
这是我在cpp.react库的文档中找到的C++代码段:
auto in = D::MakeVar(0);
auto op1 = in ->* [] (int in)
{
int result = in /* Costly operation #1 */;
return result;
};
Run Code Online (Sandbox Code Playgroud)
我从未见过这种->* []符号.首先,我认为这只是一个错字,但我也在源代码中找到了这样一个表达式:
auto volume = (width,height,depth) ->* [] (int w, int h, int d) {
return w * h * d;
};
Run Code Online (Sandbox Code Playgroud)
这是有效的C++ 11(或C++ 14)吗?这是什么意思?
Pra*_*ian 42
我看到的链接页面上的唯一示例->*是:
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;
};
Run Code Online (Sandbox Code Playgroud)
这是我的猜测 - 指针到成员操作符的D::MakeVar()重载返回的任何类型,以及该重载操作符的第二个参数是一个函数对象,即lambda表达式. ->*
至于这个例子:
auto volume = (width,height,depth) ->* [] (int w, int h, int d) {
return w * h * d;
};
Run Code Online (Sandbox Code Playgroud)
我猜什么类型的width,height与depth是,重载逗号操作符,结果产生相同类型什么MakeVar收益,或重载另一种类型->*.其余与第一个例子相同.
Bry*_*hen 17
@ Praetorian的回答是正确的.这是来自cpp.react的代码
///////////////////////////////////////////////////////////////////////////////////////////////////
/// 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));
}
Run Code Online (Sandbox Code Playgroud)
///////////////////////////////////////////////////////////////////////////////////////////////////
/// 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);
}
Run Code Online (Sandbox Code Playgroud)
你可以看到它重载了自由函数operator->*,它接受一个signal(D::MakeVar(0))和一个函子(lambda)
和自由功能operator,,需要两个信号
use*_*432 10
(作者在这里)
首先,Praetorians回答是正确的,但我想详细说明一下.
请注意,这个库仍然是非常实验性的,我仍在研究文档.所述文档的当前状态可以在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()
Run Code Online (Sandbox Code Playgroud)
它是一种绑定(绑定信号作为函数输入),但它与反向std :: bind不同.volume不是函数对象.特别是,当您调用Value()时,不会重新计算音量,当其中一个相关信号发生更改时,将重新计算音量,保存结果,并返回Value().因此它本质上是基于推送的变更传播,具有一些额外的功能(没有冗余更新,没有毛刺,可选的隐式并行化).
问题是MakeSignal在与临时信号和lambdas混合时会变得混乱:
// 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);
Run Code Online (Sandbox Code Playgroud)
没有人想读这样的东西,对吧?至少我不想.
因此,有一种替代语法将依赖项移动到左侧,由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; });
Run Code Online (Sandbox Code Playgroud)
最后,用邪恶的逗号和 - >*重载:
D::SignalT<int> volume =
(
(width, height) ->* [] (int w, int h) { return w * h; },
depth
)
->* [] (int area, int d) { return a * d; };
Run Code Online (Sandbox Code Playgroud)
正如其他人所指出的那样,问题在于,第一次看到它的人都不知道到底发生了什么.
另一方面,在使用此库时,将信号连接到函数应该是一项非常常见的任务.一旦你知道它做了什么, - >*版本更简洁,它可视化数据流图(从宽度和高度到临时区域的边缘,从区域和深度到体积的边缘).
| 归档时间: |
|
| 查看次数: |
3787 次 |
| 最近记录: |