将成员函数定义或绑定到'变量,如'关键词。没有括号的执行

时间:2014-12-06 12:51:51

标签: c++ function variables c++11 bind

有没有办法将成员函数绑定到成员变量?

让我们说我有简单的矢量结构:

struct Vec3 {
    int x, y, z;

    Vec2 xy() const { return Vec2(x, y); }
    Vec2 xz() const { return Vec2(x, z); }
    Vec2 yz() const { return Vec2(y, z); }
}

现在我可以像以下一样使用它:

Vec3 t = { 5, 3, 2 };
Vec2 s = t.xy() + t.yz();

但有没有办法可以像以下一样使用它:

Vec3 t = { 5, 3, 2 };
Vec2 s = t.xy; // this here ? execute function without '()'.

2 个答案:

答案 0 :(得分:4)

虽然C ++默认情况下不提供属性,但您可以自己轻松实现它们。 这是一种简单的方法:

#include <functional>

template<typename T>
struct property
{
public:
  typedef std::function<T()> getter;
  typedef std::function<void(T)> setter;

public:
  property(getter get, setter set)
  : get_(get)
  , set_(set)
  { }

  operator T() const { return get_(); }
  property& operator=(T x) { set_(x); return *this; }

private:
  getter get_;
  setter set_;
};

我们现在可以使用这些&#39;

重写您的Vec3类:

class Vec3
{
public:
  Vec3(int vx, int vy, int vz)
  : x(std::bind(&Vec3::get_x, this), std::bind(&Vec3::set_x, this, std::placeholders::_1))
  , y(std::bind(&Vec3::get_y, this), std::bind(&Vec3::set_y, this, std::placeholders::_1))
  , z(std::bind(&Vec3::get_z, this), std::bind(&Vec3::set_z, this, std::placeholders::_1))
  , xy(std::bind(&Vec3::get_xy, this), std::bind(&Vec3::set_xy, this, std::placeholders::_1))
  , xz(std::bind(&Vec3::get_xz, this), std::bind(&Vec3::set_xz, this, std::placeholders::_1))
  , yz(std::bind(&Vec3::get_yz, this), std::bind(&Vec3::set_yz, this, std::placeholders::_1))
  , x_(vx)
  , y_(vy)
  , z_(vz)
  { }

  property<int> x;
  property<int> y;
  property<int> z;

  property<Vec2> xy;
  property<Vec2> xz;
  property<Vec2> yz;

protected:
  int get_x() { return x_; }
  void set_x(int x) { x_ = x; }

  int get_y() { return y_; }
  void set_y(int y) { y_ = y; }

  int get_z() { return z_; }
  void set_z(int z) { z_ = z; }

  Vec2 get_xy() { return { x_, y_ }; }
  void set_xy(Vec2 xy) { x_ = xy.x; y_ = xy.y; }

  Vec2 get_xz() { return { x_, z_ }; }
  void set_xz(Vec2 xz) { x_ = xz.x; z_ = xz.y; }

  Vec2 get_yz() { return { y_, z_ }; }
  void set_yz(Vec2 yz) { y_ = yz.x; z_ = yz.y; }

private:
  int x_, y_, z_;
};

可以这样使用:

std::ostream& operator<<(std::ostream& out, const Vec2& v2)
{
  out << '[' << v2.x << ", " << v2.y << ']';
  return out;
}

std::ostream& operator<<(std::ostream& out, const Vec3& v3)
{
  out << '[' << v3.x << ", " << v3.y << ", " << v3.z << ']';
  return out;
}

int main(int argc, char** argv)
{
  Vec3 v3 { 2, 0, 1 };
  std::cout << v3 << std::endl;
  v3.y = 3;
  std::cout << v3.xy << std::endl;
  std::cout << v3.xz << std::endl;
  std::cout << v3.yz << std::endl;

  return 0;
}

正如您所看到的,您所要求的是可能的,它只需要很多代码。

请参阅ideone

上的实时示例

答案 1 :(得分:2)

您可以通过将带有用户定义的转换函数的帮助器结构添加到Vec2来实现,每个包含对父(Vec3)的引用,以便能够访问其成员。

一个工作示例(Visual Studio 2015更新3):

#include <iostream>

struct Vec2 {
    int x, y;
};

struct Vec3 {
    int x, y, z;
    struct XY {
        Vec3& outer;
        XY(Vec3& _outer) : outer {_outer} {};
        operator Vec2() { return Vec2 {outer.x, outer.y}; };
    } xy;
    struct XZ {
        Vec3& outer;
        XZ(Vec3& _outer) : outer {_outer} {};
        operator Vec2() { return Vec2 {outer.x, outer.z}; };
    } xz;
    struct YZ {
        Vec3& outer;
        YZ(Vec3& _outer) : outer {_outer} {};
        operator Vec2() { return Vec2 {outer.y, outer.z}; };
    } yz;
    Vec3(int _x, int _y, int _z) :
        xy {*this}, xz {*this}, yz {*this},
        x {_x}, y {_y}, z {_z} {};
};

int main() {
    Vec3 t {5,3,2};
    Vec2 xy = t.xy; // look, mom, no parentheses!
    Vec2 xz = t.xz; 
    Vec2 yz = t.yz;
    std::cout << xy.x << ", " << xy.y << std::endl;
    std::cout << xz.x << ", " << xz.y << std::endl;
    std::cout << yz.x << ", " << yz.y << std::endl;
}

输出:

5, 3
5, 2
3, 2
相关问题