Gautam Jha Gautam Jha - 3 months ago 11
C++ Question

Assign multibyte ASCII literals to enum values

One can assign an ASCII literal (can't call it a string) to

enum
value as following:

#include <iostream>
// Macro to handle BIG/LITTLE ENDIAN
// Endianness is suppoesed to handled in this macro
#define TEMP(X) X

enum t
{
XX = 'AA', // 0x4141 or 0100 0001 0100 0001
};

int main()
{
std::cout<<XX<<std::endl;
}


And compiler compiles it and generates a Hexa-decimal constant at compile time,
0x4141
in this case. It does generate a compilation warning as:

main.cpp:9:14: warning: multi-character character constant [-Wmultichar]
XX = 'AA', // 0x4141 or 0100 0001 0100 0001


My question here is, can we avoid this warning?

Or can we write a more elegant code to achieve similar result, probably using templates and constexpr?

I am looking for a portable alternative, so that I can get rid of this as part of refactoring without affecting the core logic.

Answer

I think you want something like this — which does not use multi-character literals BTW, rather user-defined literal called _i64, as defined below:

#include <iostream>

//implementation of user-defined literal _i64
namespace details
{
    constexpr int64_t i64(char const *s, int64_t v)
    {
        //in C++11, constexpr function body has to be one-line
        //though C++14 has relaxed this rule.
        return *s ? i64(s+1, v * 256 + *s) : v;
    }
}

constexpr int64_t operator "" _i64(char const *s, unsigned long)
{
    return details::i64(s, 0);
}

//your use-case.
enum colors
{
    red   = "AA"_i64,   //0x4141
    green = "BB"_i64,   //0x4242
    blue  = "CC"_i64    //0x4343
};

int main()
{
    std::cout << std::hex << red << std::endl;
    std::cout << std::hex << green << std::endl;
    std::cout << std::hex << blue << std::endl;
}

Output (demo):

 4141
 4242
 4343
Comments