【问题标题】:How do I get a const_iterator using auto?如何使用 auto 获得 const_iterator?
【发布时间】:2013-02-20 09:47:47
【问题描述】:

第一个问题:是否可以使用自动“强制”const_iterator? 例如:

map<int> usa;
//...init usa
auto city_it = usa.find("New York");

我只想查询,而不是更改 city_it 所指向的任何内容,所以我希望将 city_it 设置为 map&lt;int&gt;::const_iterator。但是通过使用auto,city_itmap::find() 的返回类型相同,即map&lt;int&gt;::iterator。有什么建议吗?

【问题讨论】:

  • 您想要一个特定类型的变量而不指定类型?抱歉,在这种情况下不能轻易完成。
  • 可能是static_cast&lt;map&lt;int&gt; const &amp;&gt;(usa).find("New York")?
  • map&lt;int&gt; 是一个错误(如果您的意思是std::map)。您必须至少指定两个模板参数;键类型和值类型。
  • 尽管 const auto 根据您的需要可能没问题,但应该可以将 auto city_it = usa.cfind("New York")cbegin()cend() 等保持一致......但它可能被遗忘了.您的问题有望成为一个提醒,有一天我们会收到std::cfind

标签: c++ c++11 auto


【解决方案1】:

抱歉,我认为最好的建议是根本不使用auto,因为您想要执行(隐式有效的)类型转换auto 用于推断确切类型,这不是您想要的。

就这样写吧:

std::map<std::string, int>::const_iterator city_it = usa.find("New York");

正如 MooingDuck 正确指出的那样,使用类型别名可以提高代码的可读性和可维护性:

typedef std::map<std::string, int> my_map;
my_map::const_iterator city_it = usa.find("New York");

【讨论】:

  • 相关:当我需要这样的东西时,我几乎总是typedef我的容器。
  • @MooingDuck:对。让我补充一下。谢谢
  • 或者,如果出于任何不明原因的人讨厌 typedefs,仍然有 decltype(usa.cbegin()) it = ... ;)
  • @us2012: 是的,这可行,但我无法在cbegin()cend() 之间做出决定:-D 开个玩笑
  • 非常感谢您的澄清!很高兴知道 auto 的局限性。
【解决方案2】:

从 C++17 开始,您可以像这样使用std::as_const

#include <utility>

// ...

auto city_it = std::as_const(usa).find("New York");

【讨论】:

    【解决方案3】:

    一个干净的解决方案是使用 const 对其他可修改映射的引用:

    const auto &const_usa = usa;
    auto city_it = const_usa.find("New York");
    

    这将确保您无法修改 const_usa,并将使用 const 迭代器。

    【讨论】:

      【解决方案4】:

      与@Jollymorphic 的回答相比,转换为const 并没有完全不同,但我认为拥有这样的实用单行函数很方便:

      template<class T> T const& constant(T& v){ return v; }
      

      这使得转换更吸引眼球:

      auto it = constant(usa).find("New York");
      // other solutions for direct lengths comparision
      std::map<std::string, int>::const_iterator city_it = usa.find("New York");
      auto city_it = const_cast<const std::map<std::string, int>&>(usa).find("New York");
      

      好吧,我想说,更大并不总是更好。您当然可以根据自己的喜好选择函数的名称 - as_const 或只是 const_ 是可能的替代方案。

      【讨论】:

      • 我在使用这个想法时使用了make_const
      • @GMan: make_x 至少对我来说意味着创造 一些以前没有的。这就是我选择as_const 的原因,它会更改对象上的视图
      • c++17 已将 std::as_const 添加到标题 link
      【解决方案5】:

      使用 auto 的另一种变体(同时保留可变的 usa 和 const usa):

      map<std::string, int> usa;
      //...init usa
      const auto &const_usa = usa;
      auto city_it = const_usa.find("New York");
      

      如果您在初始化后根本不需要地图是可变的,还有其他一些选项。

      您可以将 usa 定义为 const 并通过函数调用对其进行初始化:

      const map<std::string, int> usa = init_usa();
      auto city_it = usa.find("New York");
      

      或使用 lambda 初始化 const 映射:

      const auto usa = [&]()->const map<std::string, int> 
         {
         map<std::string, int> usa;
         //...init usa
         return usa;
         }();
      auto city_it = usa.find("New York");
      

      【讨论】:

        【解决方案6】:

        在 C++11 中,您可以这样做:

        decltype(usa)::const_iterator city_it = usa.find("New York");
        

        【讨论】:

          【解决方案7】:

          我现在无法对此进行测试,但我认为它可以解决问题:

          auto city_it = const_cast< const map<int> & >(usa).find("New York");
          

          【讨论】:

          • 嗯,但有什么比简单地将 map&lt;int&gt;::const_iterator 指定为类型更好的解决方案呢?无论如何,它都不会更短或更易读。
          • @us2012:从技术上讲,OP 并没有要求更短或更易读,他使用auto 请求了const_iterator,这正是它所允许的。 :P
          【解决方案8】:

          您可以使用 auto 来“跟踪”一个类型或“推断”一个类型: // deduce auto city_it = usa.find("New York");

          // track auto city_it = std::map<int>::const_iterator( usa.find("New York"));

          另外,watch 是 Herb Sutter 的现代 c++ 风格讲座,涵盖了大部分类型推导指南。 https://youtu.be/xnqTKD8uD64

          【讨论】:

          • auto city_it = {std::map&lt;int&gt;::const_iterator} usa.find("New York"); 是语法错误。你能改写你的答案并解释一下你想说什么吗?
          • 还是报错,map&lt;int&gt;不是类型。而且您没有解释“演绎”和“跟踪”之间的区别是什么。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-30
          • 1970-01-01
          • 2013-03-17
          • 2014-09-30
          • 2018-04-11
          • 1970-01-01
          相关资源
          最近更新 更多