【问题标题】:Does a forward_iterator template class make sense?forward_iterator 模板类有意义吗?
【发布时间】:2016-01-12 09:23:06
【问题描述】:

C++ 标准库包含方便的模板类std::move_iterator。鉴于std::movestd::forward 之间的密切关系,为什么没有等效的std::forward_iterator?用法示例:

template <typename C>
auto foo(C&& values)
{
    remove_reference_t<C> result {};
    result.reserve(values.size());
    std::transform(std::make_forward_iterator<C>(std::begin(values)),
                   std::make_forward_iterator<C>(std::end(values))), 
                   std::back_inserter(result), Bar());
    return result;
}

我现在可以使用foo 的想法是:

std::vector<ComplexType> values {/* lots of values */};

auto copied_fooed = foo(values); 
// or
auto moved_fooed  = foo(std::move(values));

无需写两个foos。

【问题讨论】:

  • 正确名称应为 std::forwardable_iterator 以避免与经典前向迭代器发生冲突。
  • @Jarod42 谢谢。固定(我认为)。
  • 您是在问为什么没有(提出建议?)或如何写?
  • @Barry 两者;两者并不相互排斥。要么没有充分的理由拥有一个,要么不可能拥有一个,要么是疏忽。我想知道哪个(以及为什么),当然如果是后者,我会考虑提出建议。一个有效的实现肯定会帮助回答这个问题。

标签: c++ c++11 iterator c++-standard-library


【解决方案1】:

比这要复杂一些。

对于拥有的容器,容器的 l/r 价值意味着移动迭代器可能有用。

但是对于视图,这不起作用:从右值视图移动会破坏无主状态。

实际上,这意味着基于 l/r 价值的决定是否移动是由上下文和价值共同决定的事情,这使得它变得棘手。

Range-v3 和概念可能使这更容易推理。

【讨论】:

    【解决方案2】:

    我无法回答为什么这样的事情不存在。但它肯定是可以实现的。基本上,您的 C 类型要么是左值引用(在这种情况下只是通过参数),要么不是引用(在这种情况下,使用 std::make_move_iterator)。

    首先,让我们从对任何工具包的一个重要补充开始,almost static if(稍作改动):

    namespace detail {
        enum class enabler {};
    }
    
    template <bool B>
    using EnableIf = std::enable_if_t<B, detail::enabler>;
    

    现在我们只在两个重载上使用 SFINAE:

    template <typename C,
              typename Iterator,
              EnableIf<std::is_lvalue_reference<C>::value>...>
    Iterator make_forward_iterator(Iterator i)
    {
        return i;
    }
    
    template <typename C,
              typename Iterator,
              EnableIf<!std::is_lvalue_reference<C>::value>...>
    auto make_forward_iterator(Iterator i)
    {
        return std::make_move_iterator(i);
    }
    

    或者,这可能更简单,可以只是标记调度:

    namespace detail {    
        template <typename Iterator>
        Iterator make_forward_iterator(Iterator i, std::true_type )
        {
            return i;
        }
    
        template <typename Iterator>
        auto make_forward_iterator(Iterator i, std::false_type )
        {
            return std::make_move_iterator(i);
        }
    }
    
    template <typename C, typename Iterator>
    auto make_forward_iterator(Iterator i) {
        return detail::make_forward_iterator(i, std::is_lvalue_reference<C>{});
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-02
      • 2012-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多