Tuesday, March 1, 2011

Is there a way to do a C++ style compile-time assertion to determine machine's endianness?

I have some low level serialization code that is templated, and I need to know the system's endianness at compiletime obviously (because the templates specializes based on the system's endianness).

Right now I have a header with some platform defines, but I'd rather have someway to make assertions about endianness with some templated test (like a static_assert or boost_if). Reason being my code will need to be compiled and ran on a wide range of machines, of many specialized vendor, and probably devices that don't exist in 2008, so I can't really guess what might need to go into that header years down the road. And since the code-base has an expected lifetime of about 10 years. So I can't follow the code for-ever.

Hopefully this makes my situation clear.

So does anyone know of a compile-time test that can determine endianness, without relying on vendor specific defines?

From stackoverflow
  • Hmm, that's an interesting Question. My bet is that this is not possible. I think you have to continue using macros, and go with BOOST_STATIC_ASSERT(!BIG_ENDIAN);, or static_assert in c++0x. The reason i think this is because the endian'nes is a property if your execution environment. However, static_assert is considered at compile time.

    I suggest you look into the code of the new GNU gold ELF linker. Ian Lance Taylor, its author, used templates to select the right endianness at compile time, to ensure optimal performance at run time. He explicitely instantiates all possible endians, so that he still has separate compilation (not all templates in headers) of the template definition and declaration. His code is excellent.

    Robert Gould : Yes I've not been able to figure it out myself, and as you say it might not even be possible. But I've seen the impossible done before for other situations... so maybe, just maybe someone might come up with a great idea here :)
  • There is no portable way to do this at compile time, your best bet is probably to use the Boost endian macros or emulate the methods they use.

    Robert Gould : Thanks for the link to the header. It's a good reference. And similar to what I have.
  • If you're using autoconf, you can use the AC_C_BIGENDIAN macro, which is fairly guaranteed to work (setting the WORDS_BIGENDIAN define by default)

    alternately, you could try something like the following (taken from autoconf) to get a test that will probably be optimized away (GCC, at least, removes the other branch)

    int is_big_endian()
    {
        union {
            long int l;
            char c[sizeof (long int)];
        } u;
    
        u.l = 1;
    
        if (u.c[sizeof(long int)-1] == 1)
        {
            return 1;
        }
        else
            return 0;
    }
    
    Robert Gould : Thanks, that is a nice trick. And I think I can apply it with a little reengineering. not sure yet, but its a good lead.

0 comments:

Post a Comment