// ccutl.different feature guard {{{
#ifndef CCUTL_DIFFERENT_INCLUDED
#define CCUTL_DIFFERENT_INCLUDED
// ccutl.different feature guard }}}
/* C++20
| |
__| __| | | __| |
( ( | | | |
\___| \___| \__,_| \__| _|
ccutl Core Utilities
[ccutl.different]: describes a set of types with at least one variation
Copyright (C) 2020, 2021 Justin Collier
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU 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 internalied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include
#ifndef CCUTL_NAMESPACE
#define CCUTL_NAMESPACE ctl
#endif
namespace CCUTL_NAMESPACE {
// ccutl.targ {{{
// ccutl.targ feature guard {{{
#ifndef CCUTL_TARG_INCLUDED
#define CCUTL_TARG_INCLUDED
// ccutl.targ feature guard }}}
// detail {{{
namespace detail {
namespace targ {
/// primary template for targ_::impl
template
struct impl;
/// end of iteration; type represents first type
template
struct impl {
using type = First;
};
/// iterates until i reaches target
template
struct impl {
using type = typename impl::type;
};
/// helper typedef for impl::type
template
using type = typename impl::type;
/// checks if idx can be used to index Ts...
template
inline constexpr bool
valid_indexable_pack = sizeof...(Ts) > 0 && idx < sizeof...(Ts);
} // namespace targ
} // namespace detail
// detail }}}
/* */ // clang-format off
/**
* represents the type template argument at index idx
*
* \code
* #include "ctl/targ.h"
* using x0 = ctl::targ<0, int, float, double>; // int
* using x1 = ctl::targ<1, int, float, double>; // float
* using x2 = ctl::targ<2, int, float, double>; // double
* \endcode
*
* \anchor targ
* \ingroup ccutl
*/
template
requires detail::targ::valid_indexable_pack
using targ = detail::targ::type;
/* */ // clang-format on
// ccutl.targ version guard {{{
#define CCUTL_TARG_VERSION_MAJOR 0
#define CCUTL_TARG_VERSION_MINOR 3
#define CCUTL_TARG_VERSION_PATCH 2
#elif CCUTL_TARG_VERSION_MAJOR != 0
#error ccutl.targ major version mismatch
#elif CCUTL_TARG_VERSION_MINOR != 3
#error ccutl.targ minor version mismatch
#elif CCUTL_TARG_VERSION_PATCH != 2
#warning ccutl.targ patch version mismatch
#endif
// ccutl.targ version guard }}}
// ccutl.targ }}}
// ccutl.same {{{
// ccutl.same feature guard {{{
#ifndef CCUTL_SAME_INCLUDED
#define CCUTL_SAME_INCLUDED
// ccutl.same feature guard }}}
// detail {{{
namespace detail {
namespace same {
/// checks if First, Rest... are the same
/// adheres to the spirit of the same_as conceptual redundancy;
/// (same_as = std::is_same_v and std::is_same_v)
/// all types are bidirectionally compared with each other
template
[[nodiscard]] inline constexpr bool
impl() noexcept {
if constexpr (i == sizeof...(Rest)) {
return true;
} else if constexpr (sizeof...(Rest) == 1) {
// pack is not really expanded with the ellipses (sizeof 1)
return (std::is_same_v && ...);
} else /* i < sizeof...(Rest) and sizeof...(Rest) > 1 */ {
constexpr bool this_comparison =
(std::is_same_v, Rest> && ...);
// recurse with First pushed to end to ensure two-way comparison
return this_comparison && impl();
}
}
} // namespace same
} // namespace detail
// detail }}}
/**
* describes a set of types with no variation
*
* \code
* #include "ctl/same.h"
* static_assert( same);
* static_assert(!same);
* \endcode
*
* \anchor same
* \ingroup ccutl
*/
template
concept same = sizeof...(Ts) > 0 and detail::same::impl<0, Ts...>();
// ccutl.same version guard {{{
#define CCUTL_SAME_VERSION_MAJOR 0
#define CCUTL_SAME_VERSION_MINOR 3
#define CCUTL_SAME_VERSION_PATCH 2
#elif CCUTL_SAME_VERSION_MAJOR != 0
#error ccutl.same major version mismatch
#elif CCUTL_SAME_VERSION_MINOR != 3
#error ccutl.same minor version mismatch
#elif CCUTL_SAME_VERSION_PATCH != 2
#warning ccutl.same patch version mismatch
#endif
// ccutl.same version guard }}}
// ccutl.same }}}
/**
* describes a set of types with at least one variation
*
* \code
* #include "ctl/different.h"
* auto x0 = ctl::different; // false
* auto x1 = ctl::different; // true
* \endcode
*
* \anchor different
* \ingroup ccutl
*/
template
concept different = !same;
} // namespace CCUTL_NAMESPACE
// ccutl.different version guard {{{
#define CCUTL_DIFFERENT_VERSION_MAJOR 0
#define CCUTL_DIFFERENT_VERSION_MINOR 3
#define CCUTL_DIFFERENT_VERSION_PATCH 2
#elif CCUTL_DIFFERENT_VERSION_MAJOR != 0
#error ccutl.different major version mismatch
#elif CCUTL_DIFFERENT_VERSION_MINOR != 3
#error ccutl.different minor version mismatch
#elif CCUTL_DIFFERENT_VERSION_PATCH != 2
#warning ccutl.different patch version mismatch
#endif
// vim: fmr={{{,}}} fdm=marker
// ccutl.different version guard }}}