2016-08-25 3 views
1

Можно присвоить ASCII буквального (не могу назвать это строка) до значения enum следующим образом:Присвоить многобайтовая ASCII литералов в перечислении значений

#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; 
} 

И компилятор компилирует его и генерирует гекса-десятичную константу в время компиляции, 0x4141 в этом случае. Он генерирует предупреждение о компиляции как:

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

Мой вопрос здесь, можем ли мы избежать этого предупреждения?

Или мы можем написать более элегантный код для достижения аналогичного результата, возможно, используя шаблоны и constexpr?

Я ищу портативную альтернативу, чтобы я мог избавиться от этого как части рефакторинга, не затрагивая основную логику.

+0

«Элегантный» код не использует многобайтовые символьные константы. Они просто не переносимы. http://stackoverflow.com/questions/7755202/multi-character-constant-warnings –

+1

Многосимвольное поведение констант определяется реализацией. Не используйте их, и ваш код будет более переносимым * и * не генерирует предупреждения. Что случилось с '0x4141'? – DevSolar

+0

В gcc это предупреждение можно отключить с помощью ['-Wno-multichar'] (https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wno-multichar-608). Имейте в виду, что вы полагаетесь на поведение, определенное при реализации. Таким образом, это не поможет вам, но может помочь другим читателям. –

ответ

5

Я думаю, что вы хотите что-то вроде этого — который не использует литералов из нескольких символов BTW, а определяемые пользователем буквальным называется _i64, как определено ниже:

#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; 
} 

Выход (demo):

4141 
4242 
4343 
+0

Обратите внимание, что рекурсивная тройная гимнастика не нужна в C++ 14. – Quentin

+0

@Quentin: Да. C++ 14 имеет определенную гибкость, но мое решение будет работать и на C++ 11. – Nawaz

+0

Я нахожу это увлекательным, с одной стороны, но IMO это запутывает код. Лучше избегать таких конструкций. Не совсем понятно, почему ** OP хочет многосимвольный 'enum'. Скорее всего, их можно просто избежать. – Olaf

-1

"старый" способ все еще работает

#define Word(a, b) ((a) + ((b) >> 8)) 

X= Word('A', 'A');