有没有办法将成员函数绑定到成员变量之类的东西?
假设我有简单的向量结构:
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 '()'.
虽然 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_;
};
我们现在可以使用这些“属性”重写您的 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
上的实时示例您可以通过向
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