【问题标题】:STL like container typedef shortcut?STL之类的容器typedef快捷方式?
【发布时间】:2010-09-12 14:48:07
【问题描述】:

STL 容器的常见模式是这样的:

map<Key, Value> map;
for(map<Key, Value>::iterator iter = map.begin(); iter != map.end(); ++iter)
{
  ...
}

所以为了避免编写模板参数的声明,我们可以在某处这样做:

typedef map<Key, Value> TNiceNameForAMap;

但如果此映射仅用于单个函数或单个迭代,这是一个令人讨厌的开销。

这个 typedef 有什么办法吗?

【问题讨论】:

    标签: c++ stl


    【解决方案1】:

    不确定您所说的“开销”是什么意思。如果它简化了您编写代码的方式,请使用它,否则请坚持使用常规方式。

    如果只在受限范围内使用,请将 typedef 放在同一范围内。然后它就不需要发布、记录或出现在任何 UML 图上。例如(我并不认为这是在其他方面最好的代码):

    int totalSize() {
        typedef std::map<Key, Value> DeDuplicator;
        DeDuplicator everything;
    
        // Run around the universe finding everything. If we encounter a key
        // more than once it's only added once.
    
        // now compute the total
        int total = 0;
        for(DeDuplicator::iterator i = everything.begin(); i <= everything.end(); ++i) {
            total += i->second.size(); // yeah, yeah, overflow. Whatever.
        }
        return total;
    }
    

    结合 Ferruccio 的建议(如果你使用 boost),循环变为:

    BOOST_FOREACH(DeDuplicator::pair p, everything) {
        total += p.second.size();
    }
    

    并结合 bk1e 的建议(如果您使用 C++0x 或具有其中的功能),并假设 BOOST_FOREACH 以我认为应该基于它通常可以处理隐式转换的事实与 auto 交互兼容类型:

    std::map<Key, Value> everything;
    // snipped code to run around...
    int total = 0;
    BOOST_FOREACH(auto p, everything) {
        total += p.second.size();
    }
    

    还不错。

    【讨论】:

    • 干得好!您的最后一个在紧凑性可读性方面达到了 Python 的水平。
    【解决方案2】:

    您可以使用Boost.Foreach

    【讨论】:

    • 很好,因为循环的详细程度大于 typedef 的详细程度......
    • 是的,最好的部分是语法与 C++0x foreach 结构非常相似,当您的编译器支持时,您应该能够使用正则表达式搜索和替换来更新您的代码。
    【解决方案3】:

    C++ 标准的未来版本(称为C++0x)将引入new use for the auto keyword,允许您编写如下内容:

    map<Key, Value> map;
    for(auto iter = map.begin(); iter != map.end(); ++iter)
    {
      ...
    }
    

    【讨论】:

    • 哇哦!强类型应该是这样的。
    【解决方案4】:

    我个人认为 MYMAP::iteratorma​​p::iterator 甚至 std::map::iterator 所以我总是做 typedef。唯一的开销是一行代码。

    代码编译完成后,可执行文件的大小或速度不会有任何差异。这只是关于可读性。

    【讨论】:

      【解决方案5】:

      如果 typedef 对于单个函数来说是本地的,它甚至不需要是一个 nice 名称。使用 X 或 MAP,就像在模板中一样。

      【讨论】:

      • 变量也不需要有好听的名字。但如果他们这样做就好了;-)
      【解决方案6】:

      C++0x 还将提供基于范围的 for 循环,类似于其他语言中的迭代 for 循环。

      不幸的是,GCC 还没有实现基于范围的 for(但 确实 实现了 auto)。

      编辑:同时,还要考虑对迭代器进行类型定义。它不能绕过一次性使用的 typedef(除非你把它放在头文件中,这始终是一个选项),但它使生成的代码缩短了一个 ::iterator。

      【讨论】:

        【解决方案7】:

        在过去的几年里,我确实尝试过放弃使用手动编写的循环而不是使用 STL 算法。你上面的代码可以改成:

        struct DoLoopBody {
          template <typename ValueType>
          inline void operator()(ValueType v) const {
            // ...
          }
        };
        
        std::for_each (map.begin(), map.end(), DoLoopBody ());
        

        不幸的是,DoLoopBody 类不能是本地类,这通常被强调为一个缺点。不过,我认为这是一个优势,因为现在可以单独对循环体进行单元测试。

        【讨论】:

        • 这个问题(我不是怪你对它的使用,我是怪 STL)是它不是真正的 foreach 循环,因为你指定了开始和结束条件。它更像是 perl 的 .. 范围运算符。
        • 另请注意,未来的标准 C++0x 将包含一些看起来像 lambda 函数的东西,这将使代码更紧凑(但不易于阅读,恕我直言)。关于单独测试循环体的好点。
        猜你喜欢
        • 2010-09-06
        • 2014-09-10
        • 1970-01-01
        • 2013-07-14
        • 2014-09-24
        • 2019-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多