Just a couple points:

1. Endian-ness is not generally based on the Operating System but on the processor. For example, Intel x86 processors are little-endian regardless of it running Windows or Linux.

2. Your code will always return <code>HL_LITTLE_ENDIAN</code>.  Why?  Because if

        static constexpr uint8_t endianValues[4] = {0, 1, 2, 3};

  then `endianValues[0] == 0` will always be true!  Suppose you had

        char x[4] = {'c','o','d', 'e'};

  Don't you think it would be shocking if `x[0] == 'e'` instead of `x[0] == 'c'`?

  The standard way is to use a union. Something like this:

        union endian_tester {
            uint32_t   n;
            uint8_t    p[4];
        };
    
        const endian_tester sample = {0x01020304}; // this initializes .n
    
        constexpr hl_endianness getEndianOrder() {
            return
                (0x04 == sample.p[0])               // If Little Endian Byte Order,
                    ? HL_LITTLE_ENDIAN              
                    : (0x01 == sample.p[0])         // Else if Big Endian Byte Order,
                        ? HL_BIG_ENDIAN             
                        : (0x02 == sample.p[0])     // Else if PDP Endian Byte Order,
                               ...(etc)...

  Be aware that `constexpr` isn't fully supported in my version of Visual Studio 2013 Express.

3. Not clear to me why you need to use fancy values for `HL_LITTLE_ENDIAN`, `HL_BIG_ENDIAN`, etc. You can use 1, 2, etc instead of 0x03020100, 0x00010203, etc.

4. A related question answered on Stack Overflow ([Detecting endianness programmatically in a C++ program][1])

[1]: http://stackoverflow.com/questions/1001307/detecting-endianness-programmatically-in-a-c-program