使自由函数的行为类似于成员函数(C ++)

时间:2017-05-22 20:05:01

标签: c++ templates metaprogramming std c++17

假设我在C ++中有类似以下的函数:

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

是否可以&#34;模拟&#34;可以通过将this传递给它而不是第一个参数来实现此功能的各种类的方法。 (例如,像std :: vector,std :: string ......等类。)

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

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

我可以称之为:

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

3 个答案:

答案 0 :(得分:1)

您始终可以通过传递对象的this指针来模拟成员函数。 毕竟,所有编译器都在为正确的成员函数做些事情(将this作为隐藏的第一个参数传递)。

因此,如果您希望函数foo的行为类似于成员并对Bar类型的对象(忽略此处为private / protected)进行操作,那么您可以将其声明为:

void foo(Bar* self);

并将其称为

Bar b;
foo(&b);

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

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

答案 1 :(得分:1)

不,你不能这样做。

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

除非a.b()是成员,否则您无法使用b语法。

答案 2 :(得分:1)

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