识字编码与std :: pair,解决方案?

时间:2009-06-25 05:10:12

标签: c++ literate-programming

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

我的观点是,当我回到我一两天前编写的代码时,我看到对std::pair的操纵(通常作为迭代器)我不知道自己“是什么让它自己做了什么 - > first和iter-> second意味着??? “。

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

8 个答案:

答案 0 :(得分:17)

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

答案 1 :(得分: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" );

除此之外,我看不到任何可以使事情变得更加清晰的银弹。

答案 2 :(得分:4)

typedef std::pair<bool, int> IsPresent_Value;
typedef std::pair<double, int> Price_Quantity;

...你明白了。

答案 3 :(得分:2)

你可以创建两对getter(const和non),它们只返回对第一个和第二个的引用,但是更具可读性。例如:

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

可以让你从给定的对中获得字段和值,而不必记住哪个成员拥有什么。

如果您希望大量使用它,您还可以创建一个宏,根据名称和类型为您生成这些getter:MAKE_PAIR_GETTERS(Field,string,Value,int)等等。让getter直截了当可能会让编译器对它们进行优化,因此它们在运行时不会增加任何开销;并且使用宏可以快速创建那些用于对的任何用途的getter。

答案 4 :(得分: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确实将身份和价值联系在一起。

答案 5 :(得分:2)

你可以使用boost元组,但它们并没有真正改变底层问题:你的真的想要用一个小整数类型访问对/元组的每个部分,或者你想要吗?更“识字”的代码。见this question我发布了一段时间。

然而,boost::optional是一个有用的工具,我发现它取代了很多对/元组被吹捧作为答案的情况。

答案 6 :(得分:1)

正如Alex所说,std::pair非常方便,但当它变得混乱时创建一个结构并以相同的方式使用它,看看std::pair代码,它并不复杂。

答案 7 :(得分:1)

我不喜欢std :: map中使用的std :: pair,映射条目应该有成员键和值。
我甚至使用boost :: MIC来避免这种情况。但是,boost :: MIC也需要付出代价。

此外,返回std ::对会产生不太可读的代码:

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

???

我还发现std :: pair常用于懒惰的程序员,他们需要2个值,但没想到为什么这些值需要在一起。