/*!
 * \file   /utl/impl/concepts/iterators.h
 * \brief  utl iterator concept support header
 *
 * Copyright (C) 2018 Christos Choutouridis
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
#ifndef __utl_concepts_iterator_h__
#define __utl_concepts_iterator_h__

#include <utl/core/impl.h>
#include <utl/concepts/defines.h>
#include <utl/concepts/stl.h>

/*!
 * \ingroup concepts
 * \defgroup iterators
 */
//! @{
namespace utl {

   #if CXX_CONCEPTS
   template <class I>
   _utlConcept WeaklyIncrementable =
      Semiregular<I> &&
      requires(I i) {
         { ++i } -> Same<I>&; // not required to be equality preserving
         i++;                 // not required to be equality preserving
      };
   #else
   namespace detail {
      template <typename I> using try_ppI = decltype (++(std::declval<I>()));
      template <typename I> using try_Ipp = decltype (std::declval<I>()++);
   }
   template <class I>
   _utlConcept WeaklyIncrementable =
      Semiregular<I>
      && Same<_ref_t<I>, meta::detected_t<detail::try_ppI, _ref_t<I>>>
      && meta::is_detected<detail::try_Ipp, _ref_t<I>>::value;
   #endif

   #if CXX_CONCEPTS
   template <class I>
   _utlConcept DeviceIterator =
      requires(I i) {
         { *i } -> auto&&; // Requires: i is dereferenceable
      } &&
      WeaklyIncrementable<I>;

   #else

   #endif

}

//! @}
#endif /* __utl_concepts_iterator_h__ */
