I'm trying to make a constexpr function that converts a UUID string like "f6ece560-cc3b-459a-87f1-22331582216e" to a class something like this:
class UUID { public: explicit UUID(uint8_t bytes[]);
This is what I have so far:
// Compile time hex conversion of a single character into a nibble (half-byte). constexpr uint8_t hexToNibble(char a) { // Does not work: // static_assert(a >= '0' && a <= '9' || a >= 'a' && a <= 'f' || a >= 'A' && a <= 'F', "Invalid hex character"); return a >= '0' && a <= '9' ? (a - '0') : a >= 'a' && a <= 'f' ? (a - 'a' + 10) : a >= 'A' && a <= 'F' ? (a - 'A' + 10) : 0; } // Compile time hex conversion of two characters into a byte. constexpr uint8_t hexToByte(char a, char b) { return (hexToNibble(a) << 4) + hexToNibble(b); } // Compile time string length. constexpr int strlenConst(const char* str) { return *str ? 1 + strlenConst(str + 1) : 0; } // Convert a UUID string to an array of bytes. // Example: "f6ece560-cc3b-459a-87f1-22331582216e". constexpr std::array<uint8_t, 16> UUIDFromString(const char* str) { // This does not work: // static_assert(strlenConst(str) == 36, "Invalid GUID length"); return std::array<uint8_t, 16>{ hexToByte(str[0], str[1]), hexToByte(str[2], str[3]), hexToByte(str[4], str[5]), hexToByte(str[6], str[7]), hexToByte(str[9], str[10]), hexToByte(str[11], str[12]), hexToByte(str[14], str[15]), hexToByte(str[16], str[17]), hexToByte(str[19], str[20]), hexToByte(str[21], str[22]), hexToByte(str[24], str[25]), hexToByte(str[26], str[27]), hexToByte(str[28], str[29]), hexToByte(str[30], str[31]), hexToByte(str[32], str[33]), hexToByte(str[34], str[35]), }; }
As you can see, there is a problem - it seems that it is impossible to have functional parameters that are constant expressions in the constexpr function, so you cannot execute static_assert by parameters, even if the passed value in was a constant expression.
So, I used the macro to check the length of the string and refused to check the characters.
Is there any way around this? Also, how can I easily make sure that this function is actually evaluated at compile time?
Edit : is this not the same as C ++ 11 - static_assert in constexpr function? - or at least the same answers' t work - see comments below.
Change 2 . Shafik's good answer works for a size problem, but not for checking hexadecimal characters. As far as I can tell, this is not possible - even if you use it ...
This will not work:
// Convert a UUID string to an array of bytes. // Example: "f6ece560-cc3b-459a-87f1-22331582216e". template <size_t N> constexpr std::array<uint8_t, 16> UUIDFromString(const char (&str)[N]) { // Note you have to include the null byte. static_assert(N == 37, "Invalid GUID length."); return std::array<uint8_t, 16>{ hexToByte<str[0], str[1]>(), hexToByte<str[2], str[3]>(),
Because str[0] not a constant expression.