You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何手动递归调用重载的operator->以获取底层链式指针?

如何手动触发operator->的链式调用以获取底层指针?

编译器会以特殊逻辑处理成员箭头运算符operator->:如果重载的operator->返回的不是原始指针,编译器会自动链式调用该返回值的operator->,直到得到一个原始指针为止。但手动调用obj.operator->()只能拿到该运算符直接返回的类型,而非最终的底层指针。我想知道有没有办法手动模拟编译器的这个链式调用过程,直接获取最终的底层指针值。

我尝试过三种方法,但都无法解决通用场景的问题:

#include <memory> // 用于std::addressof

struct A {
  int data;

  int* operator->() { return std::addressof(this->data); }
};

struct B {
  A operator->() { return A(); }
};

struct C {
  B operator->() { return B(); }
};

template <typename T>
struct D {
  T x;

  int* operator->() {
    // 尝试获取底层int*指针的三种方式
    // return this->x.operator->(); // (1)
    // return std::addressof(*this->x); // (2)
    // return this->x.operator->().operator->().operator->(); // (3)
  }
};

int main() {
  D<A> da;
  D<B> db;
  D<C> dc;
}

三种尝试方法的问题分析

  • (1) 直接调用T::operator->():仅对D<A>有效,因为A::operator->()直接返回int*。但对于D<B>和D<C>,调用结果分别是B和C类型,无法直接转换为int*,编译失败。
  • (2) 结合解引用和std::addressof:示例中因为A/B/C都没定义operator*(),编译器会报错。就算定义了该运算符,这种方式属于临时 workaround,而且如果被包装的T::operator->()有特殊副作用,但T::operator*()没有,就会导致逻辑不一致,不符合D作为代理需依赖T::operator->()的设计需求。
  • (3) 手动硬编码链式调用:这本质上是编译器自动执行的逻辑,但只能适配固定层数的链式调用,比如仅对D<C>有效,完全不具备通用性,改动底层类型就会失效。

背景

我正在实现一个可从任意可迭代容器构造的类型擦除视图/范围类,配套了一个类型擦除迭代器类(即示例中的D),作为底层集合迭代器的代理。C代表具体的底层迭代器(比如std::vector迭代器、std::ranges::view迭代器等)。由于类型擦除的要求,D::operator->()的返回类型不能与被包装迭代器的C::operator->()返回类型一致,否则该返回类型也需要被擦除,因此必须拿到最终的原始指针类型。

内容的提问来源于stack exchange,提问作者Die4Toast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 06:57:19