Skip to content

Instantly share code, notes, and snippets.

@gatchamix
Created July 28, 2018 02:44
Show Gist options
  • Save gatchamix/cdbf6306bab1894814a461866da29c05 to your computer and use it in GitHub Desktop.
Save gatchamix/cdbf6306bab1894814a461866da29c05 to your computer and use it in GitHub Desktop.
compile-time constant wrapper
#include <cstddef>
#include <type_traits>
//
template <auto V>
struct constant
{
using value_type = decltype(V);
auto constexpr operator-() const
{
using T = std::conditional_t<std::is_unsigned_v<value_type>,
std::make_signed_t<value_type>,
value_type>;
return constant<-static_cast<T>(V)>{};
}
auto constexpr operator--() const
{ return constant<--V>{}; }
auto constexpr operator++() const
{ return constant<++V>{}; }
template <class... Args>
auto constexpr operator()(Args&&... args) const
{ return V(static_cast<Args&&>(args)...); }
constexpr operator value_type() const
{ return V; }
};
template <auto L, auto R>
auto constexpr operator==(constant<L>, constant<R>)
{ return constant<L == R>{}; }
template <auto L, auto R>
auto constexpr operator+(constant<L>, constant<R>)
{ return constant<L + R>{}; }
template <auto L, auto R>
auto constexpr operator-(constant<L>, constant<R>)
{ return constant<L - R>{}; }
template <auto L, auto R>
auto constexpr operator*(constant<L>, constant<R>)
{ return constant<L * R>{}; }
template <auto L, auto R>
auto constexpr operator/(constant<L>, constant<R>)
{ return constant<L / R>{}; }
//
template <char... Cs>
auto constexpr operator""_c()
{
auto constexpr number = []
<std::size_t N>
(char(&&arr)[N])
{
auto base = 10u;
auto off = N;
if (N > 2 && arr[0] == '0')
{
switch (arr[1])
{
case 'x':
base = 16;
off -= 2;
break;
case 'b':
base = 2;
off -= 2;
break;
default:
base = 8;
off -= 1;
}
}
auto multiplier = 1ull;
auto number = 0ull;
for (auto i = std::size_t{ 1 }; i <= off; ++i)
{
auto const c = arr[N - i];
if (c == '\'')
{ continue; }
auto const temp = [=]
{
if (c >= 'A' && c <= 'F')
{ return c - 'A' + 10; }
else if (c >= 'a' && c <= 'f')
{ return c - 'a' + 10; }
else
{ return c - '0'; }
}();
number += temp * multiplier;
multiplier *= base;
}
return number;
}
({ Cs... });
return constant<number>{};
}
//
auto main()
-> int
{
static_assert(18446744073709551615_c == 18446744073709551615ull);
static_assert(-9223372036854775807_c == -9223372036854775807ll);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment