12

作为大多数程序员,我钦佩并尝试遵循 Litererate 编程的原则,但在 C++ 中,我经常发现自己使用std::pair, 来完成大量的常见任务。但是std::pair,恕我直言,文学编程的邪恶敌人......

我的意思是,当我回到一两天前写的代码时,我看到了一个std::pair(通常作为迭代器)的操作,我想知道“ iter->first 和 iter->second 是什么意思? ? ”。

我猜其他人在查看他们的std::pair代码时也会有同样的疑问,所以我想知道,有没有人想出一些好的解决方案来恢复使用时的读写能力std::pair

4

8 回答 8

17

std::pair是使用本质上匿名的列创建“本地”和本质上匿名类型的好方法;如果您在如此大的词汇空间上使用某个对,以至于您需要命名类型和列,我会改用普通的struct

于 2009-06-25T05:13:03.320 回答
6

这个怎么样:

struct MyPair : public std::pair < int, std::string >
{
    const int& keyInt() { return first; }
    void keyInt( const int& keyInt ) { first = keyInt; }
    const std::string& valueString() { return second; }
    void valueString( const std::string& valueString ) { second = valueString; }
};

这有点冗长,但是在您的代码中使用它可能会使事情更容易阅读,例如:

std::vector < MyPair > listPairs;

std::vector < MyPair >::iterator iterPair( listPairs.begin() );
if ( iterPair->keyInt() == 123 )
    iterPair->valueString( "hello" );

除此之外,我看不到任何能让事情变得更清晰的灵丹妙药。

于 2009-06-25T14:22:53.393 回答
4
typedef std::pair<bool, int> IsPresent_Value;
typedef std::pair<double, int> Price_Quantity;

......你明白了。

于 2009-06-25T06:05:38.000 回答
2

您可以创建两对 getter(const 和 non),它们只会返回对 first 和 second 的引用,但更具可读性。例如:

string& GetField(pair& p) { return p.first; }
int& GetValue(pair& p) { return p.second; }

将让您从给定对中获取字段和值成员,而无需记住哪个成员持有什么。

如果您希望经常使用它,您还可以创建一个宏来为您生成这些 getter,给定名称和类型:MAKE_PAIR_GETTERS(Field, string, Value, int) 左右。使 getter 变得简单可能会让编译器优化它们,因此它们不会在运行时增加开销;并且使用宏将可以轻松地为您对对的任何用途创建这些吸气剂。

于 2009-06-25T06:42:17.970 回答
2

最近我发现自己在boost::tuple使用std::pair. 您可以为每个成员定义枚举器,因此很明显每个成员是什么:

typedef boost::tuple<int, int> KeyValueTuple;
enum {
  KEY
  , VALUE
};

void foo (KeyValueTuple & p) {
    p.get<KEY> () = 0;
    p.get<VALUE> () = 0;
}

void bar (int key, int value)
{
  foo (boost:tie (key, value));
}

顺便说一句,欢迎评论使用这种方法是否存在隐藏成本。

编辑:从全局范围中删除名称。

只是关于全局命名空间的快速评论。一般来说,我会使用:

struct KeyValueTraits
{
  typedef boost::tuple<int, int> Type;
  enum {
    KEY
    , VALUE
  };
};

void foo (KeyValueTuple::Type & p) {
    p.get<KeyValueTuple::KEY> () = 0;
    p.get<KeyValueTuple::VALUE> () = 0;
}

看起来boost::fusion确实将身份和价值紧密联系在一起的情况。

于 2009-06-25T09:31:00.563 回答
2

您可以使用 boost 元组,但它们并没有真正改变潜在的问题:您是否真的想用一个小的整数类型访问对/元组的每个部分,或者您是否想要更多“识字”的代码。请参阅我不久前发布的这个问题。

但是,boost::optional是一个有用的工具,我发现它可以替代很多对/元组被吹捧为答案的情况。

于 2009-06-25T09:41:46.627 回答
1

正如 Alex 所提到的,std::pair这非常方便,但是当它感到困惑时,创建一个结构并以相同的方式使用它,看看std::pair代码,它并没有那么复杂。

于 2009-06-25T05:51:01.490 回答
1

我也不喜欢 std::map 中使用的 std::pair ,映射条目应该有成员键和值。
我什至使用 boost::MIC 来避免这种情况。然而, boost::MIC 也有代价。

此外,返回 std::pair 会导致代码不可读:

if (cntnr.insert(newEntry).second) { ... }

???

我还发现 std::pair 通常被需要 2 个值但不认为为什么需要将这些值放在一起的懒惰程序员使用。

于 2009-06-25T10:06:32.053 回答