【问题标题】:Overloading operator->() to change return value of called function重载 operator->() 以改变被调用函数的返回值
【发布时间】: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-&gt; 以自动解包指针,但无法自动将SomeOperation 的结果包装回该调用链中的SyntaxSugar,除非它已经返回... SomeOperation 的应用必须发生在您“控制”的某个函数内,以便您可以重新包装返回值,而 operator-&gt; 不能自己为您做到这一点。如果每个这样的操作都必须通过 lambda 应用(如果它有其他参数),那可以吗?
  • 基本上,您可以获得...to&lt;NodeT1&gt;().apply([myParam](auto node){ node.SomeOperation(myParam); }).to&lt;NodeT3&gt;()。会不会是太多样板文件了?
  • 如果方法集不是太大(并且不可扩展),您可以将它们添加到SyntaxSugar,以便它们调用底层方法并重新包装。
  • @MaxLanghof std::invoke 将此推广到任何可调用对象。 template&lt;typename Op&gt; auto apply(Op&amp;&amp; func) { return SyntaxSugar(std::invoke(func, ptr)); } 这将启用 .apply(&amp;NodeT2::SomeOperation)

标签: c++ c++14


【解决方案1】:

太棒了,@max-langhof

我现在基本上是这样做的

template<typename Op>
    auto SyntaxSugar::apply(Op func) -> decltype(SyntaxSugar(func(ptr)))
    { 
        if (!ptr) {
            fail();
            return SyntaxSugar(nullptr);
        }
        return SyntaxSugar(func(ptr));
    }

现在我可以了

auto result = from(startNodePtr)
    .to<NodeT1>()
    .to<NodeT2>()
    .apply([](auto node) { return node->SomeOperation(); })
    .to<NodeT3>()
    .fail_with(msg)

【讨论】:

    猜你喜欢
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    相关资源
    最近更新 更多