Loading...
Searching...
No Matches
utility/container/concept.hpp
Go to the documentation of this file.
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <concepts>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <seqan3/core/platform.hpp>
#if SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
# include <string>
namespace seqan3::detail
{
template <typename basic_string_t>
struct is_basic_string : std::false_type
{};
template <typename value_t, typename traits_t, typename allocator_t>
struct is_basic_string<std::basic_string<value_t, traits_t, allocator_t>> : std::true_type
{};
template <typename basic_string_t>
constexpr bool is_basic_string_v = is_basic_string<basic_string_t>::value;
} // namespace seqan3::detail
#endif // SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
namespace seqan3
{
template <typename type>
concept container = requires (type val, type val2, type const cval, typename type::iterator it) {
// member types
typename type::value_type;
typename type::reference;
typename type::const_reference;
/*
typename type::iterator;
requires std::forward_iterator<typename type::iterator>;
// NOTE check whether iterator is const convertible
{it} -> std::same_as<typename type::const_iterator>;
typename type::const_iterator;
requires std::forward_iterator<typename type::const_iterator>;
typename type::difference_type;
typename type::size_type;
requires std::is_same_v<
typename type::difference_type,
typename std::iterator_traits<typename type::iterator>::difference_type
>;
requires std::is_same_v<
typename std::iterator_traits<typename type::iterator>::difference_type,
typename std::iterator_traits<typename type::const_iterator>::difference_type
>;
*/
// methods and operator
{ type{} } -> std::same_as<type>; // default constructor
{ type{type{}} } -> std::same_as<type>; // copy/move constructor
{ val = val2 } -> std::same_as<type &>; // assignment
{ (&val)->~type() }; // destructor
{ val.begin() } -> std::same_as<typename type::iterator>;
{ val.end() } -> std::same_as<typename type::iterator>;
{ cval.begin() } -> std::same_as<typename type::const_iterator>;
{ cval.end() } -> std::same_as<typename type::const_iterator>;
{ val.cbegin() } -> std::same_as<typename type::const_iterator>;
{ val.cend() } -> std::same_as<typename type::const_iterator>;
requires !std::equality_comparable<typename type::value_type> || std::equality_comparable<type>;
{ val.swap(val2) } -> std::same_as<void>;
{ swap(val, val2) } -> std::same_as<void>;
{ std::swap(val, val2) } -> std::same_as<void>;
{ val.size() } -> std::same_as<typename type::size_type>;
{ val.max_size() } -> std::same_as<typename type::size_type>;
{ val.empty() } -> std::same_as<bool>;
};
template <typename type>
concept sequence_container = requires (type val, type val2, type const cval) {
requires container<type>;
// construction
{ type(typename type::size_type{}, typename type::value_type{}) };
{ type{val2.begin(), val2.end()} }; // NOTE that this could be any input iterator:
{ type{std::initializer_list<typename type::value_type>{}} };
{ val = std::initializer_list<typename type::value_type>{} } -> std::same_as<type &>;
// assignment NOTE return type is type & for std::string and void for other stl containers:
{ val.assign(val2.begin(), val2.end()) };
{ val.assign(std::initializer_list<typename type::value_type>{}) };
{ val.assign(typename type::size_type{}, typename type::value_type{}) };
// modify container
// TODO: how do you model this?
// {val.emplace(typename type::const_iterator{}, ?)} -> std::same_as<typename type::iterator>;
#if SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
{ val.insert(val.begin(), val2.front()) } -> std::same_as<typename type::iterator>;
{ val.insert(val.begin(), typename type::value_type{}) } -> std::same_as<typename type::iterator>;
// std::string is missing the const_iterator versions for insert in pre-C++11 ABI
requires detail::is_basic_string_v<type>
|| requires (type val, type val2)
#else // ^^^ workaround / no workaround vvv
requires requires (type val, type val2)
#endif // SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
{
{ val.insert(val.cbegin(), val2.front()) } -> std::same_as<typename type::iterator>;
{ val.insert(val.cbegin(), typename type::value_type{}) } -> std::same_as<typename type::iterator>;
{
val.insert(val.cbegin(), typename type::size_type{}, typename type::value_type{})
} -> std::same_as<typename type::iterator>;
{ val.insert(val.cbegin(), val2.begin(), val2.end()) } -> std::same_as<typename type::iterator>;
{
val.insert(val.cbegin(), std::initializer_list<typename type::value_type>{})
} -> std::same_as<typename type::iterator>;
};
#if SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
// std::string is missing the const_iterator versions for erase in pre-C++11 ABI
requires detail::is_basic_string_v<type>
|| requires (type val)
#else // ^^^ workaround / no workaround vvv
requires requires (type val)
#endif // SEQAN3_WORKAROUND_GCC_NO_CXX11_ABI
{
{ val.erase(val.cbegin()) } -> std::same_as<typename type::iterator>;
{ val.erase(val.cbegin(), val.cend()) } -> std::same_as<typename type::iterator>;
};
{ val.push_back(val.front()) } -> std::same_as<void>;
{ val.push_back(typename type::value_type{}) } -> std::same_as<void>;
{ val.pop_back() } -> std::same_as<void>;
{ val.clear() } -> std::same_as<void>;
// access container
{ val.front() } -> std::same_as<typename type::reference>;
{ cval.front() } -> std::same_as<typename type::const_reference>;
{ val.back() } -> std::same_as<typename type::reference>;
{ cval.back() } -> std::same_as<typename type::const_reference>;
};
template <typename type>
concept random_access_container = requires (type val) {
requires sequence_container<type>;
// access container
{ val[0] } -> std::same_as<typename type::reference>;
{ val.at(0) } -> std::same_as<typename type::reference>;
// modify container
{ val.resize(0) } -> std::same_as<void>;
{ val.resize(0, typename type::value_type{}) } -> std::same_as<void>;
};
template <typename type>
concept reservible_container = requires (type val) {
requires random_access_container<type>;
{ val.capacity() } -> std::same_as<typename type::size_type>;
{ val.reserve(0) } -> std::same_as<void>;
{ val.shrink_to_fit() } -> std::same_as<void>;
};
} // namespace seqan3
initializer_list
container
The (most general) container concept as defined by the standard library.
random_access_container
A more refined container concept than seqan3::sequence_container.
reservible_container
A more refined container concept than seqan3::random_access_container.
sequence_container
A more refined container concept than seqan3::container.
iterator
seqan3
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
platform.hpp
Provides platform and dependency checks.
string
std::swap
T swap(T... args)
type_traits
Hide me