【发布时间】:2019-02-14 10:27:45
【问题描述】:
基本上我是这样做的:
auto result = from (startNodePtr)
.to<NodeT1>()
.to<NodeT2>()
.to<NodeT3>()
.fail_with(msg)
追逐指针。你可以想象“from”和“to”返回不同 SyntaxSugar 类的模板和 fail_with 返回结果。工作正常。
但这并不是那么简单。根据我所在的节点类型,我需要调用 对底层类型的一些操作。像这样:
auto result = from(startNodePtr)
.to<NodeT1>()
.to<NodeT2>() -> SomeOperation()
.to<NodeT3>()
.fail_with(msg)
这些操作将依次返回一个指针,我需要再次包装它 在 SyntaxSugar 中。
如何正确地重载 operator-> 来做到这一点?
假设我的班级是这样的:
template<typename Pointer_T>
class SyntaxSugar
{
Pointer_T ptr;
public:
explicit SyntaxSugar(Pointer_T ptr_)
: ptr(ptr_)
{}
// all kinds of Syntax Sugar
// this one I don't get to work:
auto operator-> () { return SyntaxSugar(ptr.operator->()); }
}
【问题讨论】:
-
您可以重载
operator->以自动解包指针,但无法自动将SomeOperation的结果包装回该调用链中的SyntaxSugar,除非它已经返回...SomeOperation的应用必须发生在您“控制”的某个函数内,以便您可以重新包装返回值,而operator->不能自己为您做到这一点。如果每个这样的操作都必须通过 lambda 应用(如果它有其他参数),那可以吗? -
基本上,您可以获得
...to<NodeT1>().apply([myParam](auto node){ node.SomeOperation(myParam); }).to<NodeT3>()。会不会是太多样板文件了? -
如果方法集不是太大(并且不可扩展),您可以将它们添加到
SyntaxSugar,以便它们调用底层方法并重新包装。 -
@MaxLanghof
std::invoke将此推广到任何可调用对象。template<typename Op> auto apply(Op&& func) { return SyntaxSugar(std::invoke(func, ptr)); }这将启用.apply(&NodeT2::SomeOperation)。