代码之家  ›  专栏  ›  技术社区  ›  matkosimic

为什么我的容器概念在const std::list<double>中失败,因为begin()和end()不满足返回类型要求?

  •  1
  • matkosimic  · 技术社区  · 6 月前

    我试图在C++中定义一个容器概念,用于验证标准库容器,包括 std::list 然而,这一概念却失败了 const std::list<double> 因为 begin() end() 功能在 std::列表 不符合我的概念中迭代器的预期返回类型。具体来说,它们为非const对象返回迭代器 const_iterator 对于const对象,我目前的概念并没有正确地解释这种区别。我如何修改我的概念以正确处理这些情况?

    我尝试使用添加支票 std::as_const 但问题依然存在。我希望这个概念能同时适用于const和非const容器,但需要帮助来解决这种不匹配问题。

    template <typename C>
    concept Container = requires(C c, const C cc) {
        typename C::value_type;
        typename C::reference;
        typename C::const_reference;
        typename C::iterator;
        typename C::const_iterator;
        typename C::difference_type;
        typename C::size_type;
    
        { c.begin() } -> std::convertible_to<typename C::iterator>;
        { c.end() } -> std::convertible_to<typename C::iterator>;
    
        { c.cbegin() } -> std::convertible_to<typename C::const_iterator>;
        { c.cend() } -> std::convertible_to<typename C::const_iterator>;
    
        { cc.begin() } -> std::convertible_to<typename C::const_iterator>;
        { cc.end() } -> std::convertible_to<typename C::const_iterator>;
    
        requires std::is_copy_constructible_v<C>;
    };
    
    2 回复  |  直到 6 月前
        1
  •  1
  •   Jeff Garrett    6 月前

    只需要测试C的const删除版本:

    concept Container = requires(typename std::remove_const_t<C> c, const C cc) {
        ... /* keep the same */ ...
    };
    

    请参阅 https://godbolt.org/z/b4aMPdoWM

        2
  •  0
  •   康桓瑋    6 月前

    Container 也应该接受 cv - 裁判 合格类型,例如 list&& , violate list 等,因此您可以使用原始概念来了解实现细节并对其进行包装( c.begin() / c.end() 应该完全返回 C::iterator ):

    template <typename C>
    concept ContainerImpl = std::copy_constructible<C> &&
      requires(C c, const C cc) {
        typename C::value_type;
        typename C::reference;
        typename C::const_reference;
        typename C::iterator;
        typename C::const_iterator;
        typename C::difference_type;
        typename C::size_type;
    
        { c.begin() } -> std::same_as<typename C::iterator>;
        { c.end() } -> std::same_as<typename C::iterator>;
    
        { c.cbegin() } -> std::same_as<typename C::const_iterator>;
        { c.cend() } -> std::same_as<typename C::const_iterator>;
    
        { cc.begin() } -> std::same_as<typename C::const_iterator>;
        { cc.end() } -> std::same_as<typename C::const_iterator>;
      };
    
    template <typename C>
    concept Container = ContainerImpl<std::remove_cvref_t<C>>;