Fun with compile-time binary literal operators
Since gcc 4.7 has recently implemented user-defined literals, it is now
finally possible to define a binary literal operator template that
behaves very much like built-in literals. Of-course several things can
be improved here. One could support separator symbols like _ between
groups of digits, one could provide binary literals for signed values
(even though I have rarely seen uses of them), one could implement fixed
decimals, one could add overflow detection, etc...
Please enjoy - criticism is welcome as well:
#include <type_traits>
#include <cstdint>
namespace tools {
namespace details {
template<class...>
struct and_;
template<>
struct and_<> : std::true_type
{
};
template<class B1>
struct and_<B1> : B1
{
};
template<class B1, class B2>
struct and_<B1, B2> : std::conditional<B1::value, B2, B1>::type
{
};
template<class B1, class B2, class B3, class... Bn>
struct and_<B1, B2, B3, Bn...> : std::conditional<B1::value,
and_<B2, B3, Bn...>, B1
::type
{
};
template<char...>
struct binary_to_decimal;
template<>
struct binary_to_decimal<>
{
static constexpr std::uintmax_t value = 0;
};
template<char D1, char... Dn>
struct binary_to_decimal<D1, Dn...>
{
static constexpr std::uintmax_t value =
(UINTMAX_C(1) << sizeof...(Dn)) * (D1 - '0') +
binary_to_decimal<Dn...>::value;
};
template<char D>
struct is_binary_digit : std::integral_constant<bool,
D == '0' || D == '1'
{
};
} // details
template <char... Digits>
constexpr std::uintmax_t operator "" _b()
{
static_assert(details::and_<details::is_binary_digit<
Digits>...>::value,
"binary digits must be 0 or 1");
return details::binary_to_decimal<Digits...>::value;
}
}
Technically it would be easily possible to prevent successful
overload-resolution the template (via sfinae means), if the digits are
not all valid, but this gave in my opinion a worse diagnostic than by
means of a static assertion.
Since gcc does currently not properly resolve using-declarations of
literal operators, you need a using directive. Here is a short example
code based on above implementation which demonstrates that the literals
are evaluated during compile-time:
using namespace tools;
static_assert(0_b == 0, "Ouch");
static_assert(1_b == 1, "Ouch");
static_assert(01_b == 1, "Ouch");
static_assert(10_b == 2, "Ouch");
static_assert(11_b == 3, "Ouch");
static_assert(00011_b == 3, "Ouch");
static_assert(1000_b == 8, "Ouch");
static_assert(1111_b == 15, "Ouch");
static_assert(101101110111000001100101110_b == 96174894, "Ouch");
static_assert(1110001100001010001001100011111101_b == 15236372733, "Ouch");
Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]