使自由函数的行为像成员函数 (C++)

Make a free function behave like a member function (C++)

假设我在 C++ 中有如下函数:

template<typename Container>
void doNothing(Container * container) {
    for (auto element: container) {
         std::cout << element;
    }
}

是否可以通过向其传递 this 而不是第一个参数来实现此功能的各种 class 上的 "simulate" 方法。 (例如 class 如 std::vector、std::string ... 等)。

所以基本上不必将其用作:

std::vector<double> a{1, 2, 0.5}:
doNothing(a);

我可以这样称呼它:

std::vector<double> a{1, 2, 0.5}:
a.doNothing();

您始终可以通过传递对象的 this 指针来模拟成员函数。 毕竟,这就是编译器为适当的成员函数所做的全部工作(将 this 作为隐藏的第一个参数传递)。

因此,如果您希望函数 foo 表现得像一个成员并在类型 Bar 的对象(此处忽略 private/protected)上操作,那么您可以将其声明为:

void foo(Bar* self);

并称其为

Bar b;
foo(&b);

(或来自 Bar 成员:foo(this);

然后它将能够访问 b 的成员并通过取消引用 self 指针来调用它的函数。

不,你不能那样做。

调用 a.b() 中的 this 参数是隐式的,无法伪造隐式参数。

除非 b 是成员,否则 a.b() 语法根本不可用。

template<class F>
struct poly_mem_ptr_t{
  F f;
  template<class T>
  friend auto operator->*( T* t, poly_mem_ptr_t self )const{
    return
      [t, f=self.f](auto&&...args)->decltype(auto){
        return f(t, decltype(args)(args)...); 
      };
  }
  template<class T>
  friend auto operator->*( T& t, poly_mem_ptr_t self )const{
    return std::addressof(t)->*self;
  }
};

template<class F>
poly_mem_ptr_t<F> poly_mem_ptr(F f){ return {std::move(f)}; }

示例使用:

auto do_nothing = poly_mem_ptr([](auto* ptr){ doNothing(ptr); });

std::vector<int> v={1,2,3};
(v->*do_nothing)();

不完全是你想要的,但接近。

作为福利,您可以添加

  template<class...Ts>
  friend decltype(auto) operator->*( std::variant<Ts...>& var, poly_mem_ptr_t self )const{
    return [&var, f=self.f](auto&&...args) {
      return std::visit( [&](auto&&t)->decltype(auto){
        return f( decltype(t)(t), decltype(args)(args)... );
      }, var);
    };
  }

现在您可以 std::variant 并使用这些 poly_mem_ptr 作为访客。

通过一些工作,您还可以构建一个增强的 std::any 来支持一组固定的 poly_mem_ptr