如何为标准库容器定义 C++ 概念?

use*_*168 9 c++ c++-concepts

我想要标准库容器的 C++ 概念的实现。

提前谢谢了!

use*_*168 8

使用 C++ 概念库修正了 Caleth 的答案:

template <class ContainerType> 
concept Container = requires(ContainerType a, const ContainerType b) 
{
    requires std::regular<ContainerType>;
    requires std::swappable<ContainerType>;
    requires std::destructible<typename ContainerType::value_type>;
    requires std::same_as<typename ContainerType::reference, typename ContainerType::value_type &>;
    requires std::same_as<typename ContainerType::const_reference, const typename ContainerType::value_type &>;
    requires std::forward_iterator<typename ContainerType::iterator>;
    requires std::forward_iterator<typename ContainerType::const_iterator>;
    requires std::signed_integral<typename ContainerType::difference_type>;
    requires std::same_as<typename ContainerType::difference_type, typename std::iterator_traits<typename
ContainerType::iterator>::difference_type>;
    requires std::same_as<typename ContainerType::difference_type, typename std::iterator_traits<typename
ContainerType::const_iterator>::difference_type>;
    { a.begin() } -> std::same_as<typename ContainerType::iterator>;
    { a.end() } -> std::same_as<typename ContainerType::iterator>;
    { b.begin() } -> std::same_as<typename ContainerType::const_iterator>;
    { b.end() } -> std::same_as<typename ContainerType::const_iterator>;
    { a.cbegin() } -> std::same_as<typename ContainerType::const_iterator>;
    { a.cend() } -> std::same_as<typename ContainerType::const_iterator>;
    { a.size() } -> std::same_as<typename ContainerType::size_type>;
    { a.max_size() } -> std::same_as<typename ContainerType::size_type>;
    { a.empty() } -> std::same_as<bool>;
};
Run Code Online (Sandbox Code Playgroud)

  • 语法 `{ expression } -&gt; typename &lt;TYPE&gt;` [似乎无法编译](https://godbolt.org/z/5vhab4MG1)。这是否可能是概念在标准化之前就被删除的一个特征? (4认同)

Cal*_*eth 6

有预概念容器要求。作为一个看起来像这样的概念

template <class E>
concept default_erasable = requires(E * p) {
    std::destroy_at(p);
};

template <class E, class T, class A>
concept allocator_erasable = requires(A m, E * p) {
    requires std::same_as<typename T::allocator_type, typename std::allocator_traits<A>::rebind_alloc<E>>;
    std::allocator_traits<A>::destroy(m, p);
};

template <class T>
concept allocator_aware = requires (T a) {
    { a.get_allocator() } -> std::same_as<typename T::allocator_type>;
};

template <class T>
struct is_basic_string : std::false_type {};

template <class C, class T, class A>
struct is_basic_string<std::basic_string<C, T, A>> : std::true_type {};

template <class T>
constexpr bool is_basic_string_v = is_basic_string<T>::value;

template <class E, class T>
concept erasable = (is_basic_string_v<T> && default_erasable<E>)
                || (allocator_aware<T> && allocator_erasable<E, T, typename T::allocator_type>) 
                || (!allocator_aware<T> && default_erasable<E>);

template <class T>
concept container = requires(T a, const T b)
{
    requires std::regular<T>;
    requires std::swappable<T>;
    requires erasable<typename T::value_type, T>;
    requires std::same_as<typename T::reference, typename T::value_type &>;
    requires std::same_as<typename T::const_reference, const typename T::value_type &>;
    requires std::forward_iterator<typename T::iterator>;
    requires std::forward_iterator<typename T::const_iterator>;
    requires std::signed_integral<typename T::difference_type>;
    requires std::same_as<typename T::difference_type, typename std::iterator_traits<typename T::iterator>::difference_type>;
    requires std::same_as<typename T::difference_type, typename std::iterator_traits<typename T::const_iterator>::difference_type>;
    { a.begin() } -> std::same_as<typename T::iterator>;
    { a.end() } -> std::same_as<typename T::iterator>;
    { b.begin() } -> std::same_as<typename T::const_iterator>;
    { b.end() } -> std::same_as<typename T::const_iterator>;
    { a.cbegin() } -> std::same_as<typename T::const_iterator>;
    { a.cend() } -> std::same_as<typename T::const_iterator>;
    { a.size() } -> std::same_as<typename T::size_type>;
    { a.max_size() } -> std::same_as<typename T::size_type>;
    { a.empty() } -> std::convertible_to<bool>;
};
Run Code Online (Sandbox Code Playgroud)

您可能想添加requires std::ranges::range<T>;概念部分排序。

在 coliru 上查看

  • 完美 - 谢谢 - 这对我来说似乎是很常见的事情我想知道为什么它不是标准的一部分...... (4认同)

小智 5

实际在 C++\xe2\x80\xa6 中编译的修复版本:

\n\n
template <class ContainerType>\nconcept Container = requires(ContainerType a, const ContainerType b)\n{\n    requires std::regular<ContainerType>;\n    requires std::swappable<ContainerType>;\n    requires std::destructible<typename ContainerType::value_type>;\n    requires std::same_as<typename ContainerType::reference, typename ContainerType::value_type &>;\n    requires std::same_as<typename ContainerType::const_reference, const typename ContainerType::value_type &>;\n    requires std::forward_iterator<typename ContainerType::iterator>;\n    requires std::forward_iterator<typename ContainerType::const_iterator>;\n    requires std::signed_integral<typename ContainerType::difference_type>;\n    requires std::same_as<typename ContainerType::difference_type, typename std::iterator_traits<typename ContainerType::iterator>::difference_type>;\n    requires std::same_as<typename ContainerType::difference_type, typename std::iterator_traits<typename ContainerType::const_iterator>::difference_type>;\n    { a.begin() } -> std::same_as<typename ContainerType::iterator>;\n    { a.end() } -> std::same_as<typename ContainerType::iterator>;\n    { b.begin() } -> std::same_as<typename ContainerType::const_iterator>;\n    { b.end() } -> std::same_as<typename ContainerType::const_iterator>;\n    { a.cbegin() } -> std::same_as<typename ContainerType::const_iterator>;\n    { a.cend() } -> std::same_as<typename ContainerType::const_iterator>;\n    { a.size() } -> std::same_as<typename ContainerType::size_type>;\n    { a.max_size() } -> std::same_as<typename ContainerType::size_type>;\n    { a.empty() } -> std::same_as<bool>;\n};\nstatic_assert(Container<std::vector<unsigned char>>);\nstatic_assert(Container<std::string>);\n
Run Code Online (Sandbox Code Playgroud)\n