Skip to content

Instantly share code, notes, and snippets.

@oktal
Created May 13, 2013 20:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oktal/5571203 to your computer and use it in GitHub Desktop.
Save oktal/5571203 to your computer and use it in GitHub Desktop.
Safe compile-time binary converter
#include <iostream>
#include <type_traits>
#include <cassert>
namespace details {
template<typename T> struct DigitValue {
};
template<> struct DigitValue<int> {
static constexpr int v(const int value) { return value; }
};
template<> struct DigitValue<char> {
static constexpr int v(const char value) { return value - '0'; }
};
constexpr bool is_binary(int d) {
return d == 0 || d == 1;
}
constexpr bool is_binary(char c) {
return is_binary(c - '0');
}
}
template<unsigned Result, typename Vals, Vals ...digits> struct BinaryConverterBase {
};
template<unsigned Result, typename Vals, Vals Head, Vals ...Tail>
struct BinaryConverterBase<Result, Vals, Head, Tail...> {
static_assert(details::is_binary(Head), "Encoutered a non-binary value (must be either 0 or 1)");
static constexpr unsigned value = BinaryConverterBase<2 * Result + details::DigitValue<Vals>::v(Head),
Vals, Tail...>::value;
};
template<unsigned Result, typename Vals> struct BinaryConverterBase<Result, Vals> {
static constexpr unsigned value = Result;
};
template<typename T, T ...digits> struct BinaryConverter :
public BinaryConverterBase<0, typename std::remove_cv<T>::type, digits...>
{
typedef typename std::remove_cv<T>::type type;
static_assert(std::is_same<type, int>::value || std::is_same<type, char>::value,
"Supported types are int and char");
};
template<char ...digits> constexpr unsigned operator"" _b() {
return BinaryConverter<char, digits...>::value;
}
static_assert(BinaryConverter<const int, 0>::value == 0, "0b != 0");
static_assert(BinaryConverter<int, 0, 1, 1, 1>::value == 7, "0111b != 7");
static_assert(BinaryConverter<int, 1, 0, 1, 1>::value == 11, "1011b != 11");
static_assert(BinaryConverter<char, '0'>::value == 0, "0b != 0");
static_assert(BinaryConverter<const char, '0','1', '1', '1'>::value == 7, "0111b != 7");
static_assert(BinaryConverter<char, '1', '0', '1', '1'>::value == 11, "1011b != 11");
int main() {
assert(0111_b == 0x7);
assert(11111111_b == 0xFF);
assert(10101010_b == 0xAA);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment