通常我会发现自己使用std :: pair来定义两个相关量的逻辑分组作为函数参数/返回值.一些例子:row/col,tag/value等.
通常我应该滚动自己的类而不是仅使用std :: pair.当事情开始崩溃时很容易看到 - 当代码变得乱七八糟时,第一,第二,它很难记住什么是什么 - std::pair
传达的意义不如一种类型Position
.
您发现什么是将std :: pair的功能包装在一个传达真正含义的类型中的最佳方法?
以下是我考虑过的一些事情:
typedef std::pairPosition;
这至少在传递类型时为类型赋予了有意义的名称,但是类型没有强制执行,它仍然只是一对,并且大多数相同的问题仍然存在.然而,编写起来非常简单.
struct Position : public std::pair{ typedef std::pair 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; } };
这样做更好,因为我们可以通过合理描述性的名称访问变量.这里的问题是你仍然可以访问第一个和第二个,因此抽象容易泄漏.此外,通过函数访问简单变量会使语法烦人.
显而易见的下一步是将继承设为私有:
struct Position : private std::pair{ typedef std::pair 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... };
所以现在至少我们已经摆脱了对第一和第二的访问权限,但现在又出现了一个新问题.当我们想要将类型存储在std :: set中时,我们现在无法访问运算符 所以现在我们有了简单的变量访问,但是现在定义重载运算符更加困难,因为我们实际上每次都必须重新实现它们,而不是仅将它们转发给对的实现. 是否有任何我忽略的解决方案,使这很容易没有缺点?如果没有哪个你更喜欢? 这就是Boost.Tuple的用途. 但你现在可能应该使用std :: tuple ...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
1> Ferruccio..: