I am trying to define a Container concept in C++ that validates standard library containers, including std::list
. However, the concept fails for const std::list<double>
because the begin()
and end()
functions in std::list
do not meet the expected return types for iterators in my concept. Specifically, they return iterator for non-const objects and const_iterator
for const objects, and my current concept does not account for this distinction properly. How can I modify my concept to handle these cases correctly?
I tried adding checks using std::as_const
but the issue persists. I expected the concept to pass for both const and non-const containers but need help addressing this mismatch.
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>;
};
One just needs to test the const-removed version of C:
concept Container = requires(typename std::remove_const_t<C> c, const C cc) {
... /* keep the same */ ...
};