【发布时间】:2008-10-14 18:48:08
【问题描述】:
我经常发现自己使用 std::pair 将两个相关量的逻辑分组定义为函数参数/返回值。一些示例:行/列、标签/值等。
很多时候我真的应该滚动我自己的课程,而不是仅仅使用 std::pair。很容易看出事情何时开始崩溃 - 当代码中到处都是 make_pair 时,首先,其次,很难记住什么是什么 - std::pair<int, int> 传达的意义不如 Position 类型。
您发现了将 std::pair 的功能封装在传达真实含义的类型中的最佳方法是什么?
以下是我考虑过的一些事情:
typedef std::pair<int, int> Position;
这至少在传递类型时为类型提供了一个有意义的名称,但是类型不是强制的,它实际上仍然只是一对,并且大多数相同的问题仍然存在。不过这写起来很简单。
struct Position : public std::pair<int, int>
{
typedef std::pair<int, int> Base;
Position() : Base() {}
Position(const Position &x) : Base(x) {}
Position(int a, int b) : Base(a, b) {}
int &row() { return first; }
const int &row() const { return first; }
int &col() { return second; }
const int &col() const { return second; }
};
这样更好,因为我们可以通过一个合理的描述性名称来访问变量。这里的问题是您仍然可以访问 first 和 second,因此抽象很容易泄漏。此外,通过函数访问简单变量会使语法烦人。
下一步显然是将继承设为私有:
struct Position : private std::pair<int, int>
{
typedef std::pair<int, int> Base;
Position() {}
Position(const Position &x) : Base(x) {}
Position(int a, int b) : Base(a, b) {}
int &row() { return first; }
const int &row() const { return first; }
int &col() { return second; }
const int &col() const { return second; }
bool operator<(const Position &x) const { return Base(*this) < Base(x); }
// other forwarding operators as needed...
};
所以现在至少我们已经摆脱了对 first 和 second 的访问权限,但是现在弹出了一个新问题。当我们想将类型存储在 std::set 中时,我们现在无法访问 operator
struct Position
{
Position() {}
Position(const Position &x) : row(x.row), col(x.col) {}
Position(int row, int col) : row(row), col(col) {}
int row, col;
};
bool operator<(const Position &a, const Position &b)
{
return a.row < b.row || (!(b.row < a.row) && a.col < b.col);
}
// more overloads as needed
所以现在我们有了简单的变量访问,但现在定义重载的操作符更加痛苦,因为我们实际上每次都必须重新实现它们,而不是仅仅将它们转发到对的实现中......
是否有任何我忽略的解决方案可以让这件事变得简单而没有缺点?如果没有,你会更喜欢哪一个?
【问题讨论】: