2

我有一个 CRTP 类,在重构期间为了 API 清晰,我想要一个包含方法的命名匿名结构,而不是让所有方法都在类范围内。问题是,这些方法需要访问外部范围。例如:

template<typename T>
class sample_class {
public:
   struct  {
      void do_something() {
          auto& result = get_ref().something_else(); //get_ref() out of inner struct scope
          ...
      }
   } inner;

private:
  T& get_ref() { return static_cast<T&>(*this); }
};

有什么技术可以使这项工作吗?特别是 C++14 和 gcc7,因为我不相信匿名结构在技术上符合标准。

4

2 回答 2

3

另一个类中的类没有指向封闭类的 this 指针的隐式指针。

如果您希望它具有指向封闭类实例的指针,请显式存储它。

struct  {
  void do_something() {
    auto& result = p_sample->get_ref().something_else(); //get_ref() out of inner struct scope
    ...
  }
  sample* p_sample;
} inner;

或传递一个指向方法的指针:

  void do_something(sample* psample) {
    auto& result = p_sample->get_ref().something_else(); //get_ref() out of inner struct scope
    ...
  }

有一些方法可以使用指针算法来生成看似指向外部类的指针,但它们被 C++ 中极其复杂和危险的规则所困。

除了一些访问/命名规则等之外,其他类中定义的类并不神奇。它们可以(理论上)存在于其他环境中;可以存在于堆栈中的inner某个地方,而不是在sample.

于 2022-02-14T20:23:40.973 回答
1

是的,你减去offsetoffrom的结果this

auto &self = *reinterpret_cast<sample_class *>(reinterpret_cast<char *>(this) - offsetof(sample_class, inner));

这在技术上可能是 UB(请参阅 的可达性规则std::launder),但在实践中应该足够好。

但我认为,获得一个好看的方法名称并不能保证这种骇人听闻的方式。只需替换inner.do_something()inner_do_something().

于 2022-02-14T20:25:18.113 回答