/* Copyright (C) 1991-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library 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 2.1 of the License, or (at your option) any later version.
The GNU C Library 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 the GNU C Library; if not, see
. */
/* This header is separate from features.h so that the compiler can
include it implicitly at the start of every compilation. It must
not itself include or any other header that includes
because the implicit include comes before any feature
test macros that may be defined in a source file before it first
explicitly includes a system header. GCC knows the name of this
header in order to preinclude it. */
/* glibc's intent is to support the IEC 559 math functionality, real
and complex. If the GCC (4.9 and later) predefined macros
specifying compiler intent are available, use them to determine
whether the overall intent is to support these features; otherwise,
presume an older compiler has intent to support these features and
define these macros by default. */
/* wchar_t uses Unicode 10.0.0. Version 10.0 of the Unicode Standard is
synchronized with ISO/IEC 10646:2017, fifth edition, plus
the following additions from Amendment 1 to the fifth edition:
- 56 emoji characters
- 285 hentaigana
- 3 additional Zanabazar Square characters */
// Copyright (c) 2019 Bastien Penavayre
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
// Copyright (c) 2019 Bastien Penavayre
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
// Copyright (c) 2019 Bastien Penavayre
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
namespace unconstexpr {
// unique id section
using id_value = const int *;
template
struct id_t {};
template
struct unique_id {
static constexpr int value = 0;
constexpr unique_id(T const &) {}
constexpr operator id_value() const { return &value; }
};
/**
The following is one of the base of this hack!
This works because the conversion from unique_id to bool is delayed,
therefore the lambda is a new one at each instantiation of a template
depending on that non-type template which leads to 'name' to have a different
value at each deduction
*/
} // namespace unconstexpr
// Copyright (c) 2019 Bastien Penavayre
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
namespace unconstexpr {
template
struct value_t {
static constexpr auto value = V;
};
template
struct value_lambda {
static constexpr auto value = Lambda{}();
};
} // namespace unconstexpr
// force each call to be a new template instanciation
// checks that Meta is a meta_var
// simple workaround for lack of concepts
namespace unconstexpr {
template
constexpr auto current_index(Meta const& = {}) {
constexpr auto idx = Meta::template last_index();
return idx;
}
template
constexpr auto current_value(Meta const& = {}) {
constexpr auto idx = current_index();
return Meta::template value();
}
namespace increment_hack {
/**
To circomvent bug in clang:
Constexpr variables aren't implicitly captured in lambda expressions if we are
in a template context. As some of the following constexpr variable might be
invalid non-type template parameter, we defines them here so that we can
access them from a default-construstible lambda and pass it around.
*/
template
struct increment_info {
static constexpr auto idx = current_index();
static constexpr auto value = Meta::template value();
static constexpr auto nvalue = value + ValueInc::value;
};
} // namespace increment_hack
template , id_value Id = unique_id([] {}), bool = Meta::is_meta_var>
constexpr auto increment(Meta const& = {}) {
using hack = increment_hack::template increment_info;
constexpr auto idx = hack::idx;
constexpr auto value = hack::value;
constexpr auto nvalue = hack::nvalue;
constexpr auto nidx = idx + Meta::increment;
constexpr auto lambda_next = [] { return hack::nvalue; };
using value_holder = value_lambda;
static_assert(Meta::template set_value);
if constexpr (postincrement)
return value;
else
return nvalue;
}
template
constexpr auto set(Meta const& = {}, value_t const& = {}) {
constexpr auto idx = current_index();
constexpr auto nidx = idx + Meta::increment;
using holder = value_t;
static_assert(Meta::template set_value);
return Value;
}
template
constexpr auto set(Meta const& = {}, Lambda const& = {}) {
constexpr auto idx = current_index();
constexpr auto nidx = idx + Meta::increment;
using holder = value_lambda;
static_assert(Meta::template set_value);
return holder::value;
}
} // namespace unconstexpr
// Copyright (c) 2019 Bastien Penavayre
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
namespace unconstexpr {
template
struct meta_value {
template
struct flagCheck {
template
friend constexpr auto unconstexpr_adl(flagCheck, id_t const &);
};
template
struct flagGet {
template
friend constexpr auto unconstexpr_adl(flagGet, id_t const &);
};
template >
struct writer {
template
friend constexpr auto unconstexpr_adl(flagCheck, id_t const &) {
return true;
}
template
friend constexpr auto unconstexpr_adl(flagGet, id_t const &) {
return ValueHolder::value;
}
};
static_assert(sizeof(writer<0, value_t>));
template {}, T{}))>
static constexpr bool exists(int) {
return true;
}
template
static constexpr bool exists(float) {
return false;
}
template
static constexpr auto last_index() {
using unique_type = id_t;
constexpr bool ok = exists(int{});
if constexpr (ok)
return last_index();
else
return Index;
}
template
static constexpr auto value() {
using unique_type = id_t;
return unconstexpr_adl(flagGet{}, unique_type{});
}
static constexpr bool is_meta_var = true;
static constexpr auto increment = Inc;
template
static constexpr bool set_value = sizeof(writer);
};
} // namespace unconstexpr
// Copyright (c) 2019 Bastien Penavayre
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
namespace unconstexpr {
template
constexpr auto operator*(Meta const &) {
return current_value();
}
template
constexpr auto operator++(Meta const &, Opt...) {
constexpr bool is_postincrement = sizeof...(Opt) != 0;
using inc = value_t;
return increment();
}
template
constexpr auto operator--(Meta const &, Opt...) {
constexpr bool is_postincrement = sizeof...(Opt) != 0;
using inc = value_t<-1 * Meta::increment>;
return increment();
}
template
constexpr auto operator+=(Meta const &c, value_t const &) {
static_assert(sizeof(increment, Id>()));
return c;
}
template
constexpr auto operator+=(Meta const &c, Lambda const &) {
static_assert(sizeof(increment, Id>()));
return c;
}
template
constexpr auto operator<<(Meta const &c, value_t const &) {
static_assert(sizeof(set()));
return c;
}
template
constexpr auto operator<<(Meta const &c, Holder const &) {
static_assert(sizeof(set()));
return c;
}
} // namespace unconstexpr