Препроцессор:Как правильно задавать константы/литералы определенного интгр типа?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 16.04.19 21:23
Оценка:
Здравствуйте!

В итоге вроде бы решил самым простым способом, без изысков
Хочу:
сonstexpr uintptr_t a = 140721923966320;
cout<<a;



Но: почему-то полагал, что не сработает, и что надо добавить суффикс типа (не "типа", а типа):
uintptr_t ptr = 12345ull;


Размер указателя зависит от платформы, поэтому решил:
#ifdef WIN32 /* например */
    #define UPTR_SUFF ul
#elif defined(WIN64)
    #define UPTR_SUFF ull
#endif

#define DECLARE_CONST_ADDR_SUFFIX_HELPER(suff) suff

// не работает
#define DECLARE_CONST_ADDR(addr, suff)         addr ## DECLARE_CONST_ADDR_SUFFIX_HELPER(suff)
// так тоже
#define DECLARE_CONST_ADDR(addr, suff)         addr ## suff


Как быть?

В итоге-то вроде работает по самому простому пути, и в случае чего проще переопределить сам макрос DECLARE_CONST_ADDR или есть вариант задать с помощью UPTR_SUFF?
А если слева будет какой-то объект, который хочет другое, например short unsigned?
Маньяк Робокряк колесит по городу
Re: Препроцессор:Как правильно задавать константы/литералы определенного интгр т
От: watchmaker  
Дата: 16.04.19 22:46
Оценка: 2 (1)
Здравствуйте, Marty, Вы писали:


M>В итоге вроде бы решил самым простым способом, без изысков

M>Хочу:
M>сonstexpr uintptr_t a = 140721923966320;
M>cout<<a;
M>

И что мешает писать прямо вот так, как выше написано?

M>Но: почему-то полагал, что не сработает

Полагал? То есть сейчас так не полагаешь? Ну и правильно.


M>Размер указателя зависит от платформы, поэтому решил:

M>
M>#ifdef WIN32 /* например */
M>    #define UPTR_SUFF ul
M>#elif defined(WIN64)
M>    #define UPTR_SUFF ull
M>#endif

M>#define DECLARE_CONST_ADDR_SUFFIX_HELPER(suff) suff

M>// не работает
M>#define DECLARE_CONST_ADDR(addr, suff)         addr ## DECLARE_CONST_ADDR_SUFFIX_HELPER(suff)
M>// так тоже
M>#define DECLARE_CONST_ADDR(addr, suff)         addr ## suff
M>



Во-первых, все загоны с суффиксами ul и ull тут не нужны. Совсем не нужны.
Во-вторых, такие макросы пишутся так:
#define DECLARE_CONST_ADDR_HELPER(addr, suff)   addr ## suff
#define DECLARE_CONST_ADDR(addr, suff)          DECLARE_CONST_ADDR_HELPER(addr, suff)

// DECLARE_CONST_ADDR(123, UPTR_SUFF) раскроется в 123ul, если UPTR_SUFF определён как ul

В-третьих, не вздумай их использовать, потому что пункт первый :)

Суффиксы l и ll задают ограничение снизу на тип:
auto i = 1;   // decltype(i) -> int
auto j = 2l;  // decltype(j) -> long
auto k = 3ll; // decltype(k) -> long long

Тебе же уже известно какой тим нужно получить — uintptr_t. Значит никакие дополнительные ограничения не нужны.
Важно только знаковый тип или нет. То есть суффикс u для uintptr_t и никакого для intptr_t.

M>Как быть?

Что именно надо-то? Получить uintptr_t с таким же значением как и в числовой записи ? Пиши uintptr_t{42u}
Ну или через свои макросы как-то так:
#define DECLARE_CONST_ADDR(addr) uintptr_t{addr ## u}

Cуффикс u покажет что нужно беззнаковое число (формально это важно в случаях, когда значение представимо в самом широком беззнаковом типе, но не представимо в самом широком знаковом типе). А запись uintptr_t{x} (в отличии от например uintptr_t(x)) скажет компилятору ругаться, если число не влезает в тип (типичная ситуация, когда платформа поддерживает 64-х битные целые числа, но использует 32-х битные указатели).
Если же вопрос сужения не волнует, то достаточно написать #define DECLARE_CONST_ADDR(addr) addr :)

M>А если слева будет какой-то объект, который хочет другое, например short unsigned?

Вот это дельный вопрос. В С++ отсутствуют compound literals, которые есть в C. А по грамматике в explicit type conversion можно использовать только одно слово (а в unsigned short их два).
Поэтому подобное можно сделать только через алиас типа:
(unsinged short){30} // нельзя в C++
unsinged short{30} // нельзя в C++

using unsinged_short = unsigned short;
unsinged_short{30}; // можно

(unsigned short)(30) // тоже можно, не нет защиты от сужения, если вместо 30 окажется какое-нибудь огромное число

Но обычно подобные конструкции не нужны. Например, потому что есть переменные и константы:
constexpr unsigned short a{30};
Re[2]: Препроцессор:Как правильно задавать константы/литералы определенного интг
От: _NN_ www.nemerleweb.com
Дата: 17.04.19 07:57
Оценка:
Здравствуйте, watchmaker, Вы писали:

В MSVC компилируется.
Записать в баг или в фичу ?
int main()
{
    constexpr auto A = unsigned short{10};
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Препроцессор:Как правильно задавать константы/литералы определенного интгр т
От: B0FEE664  
Дата: 17.04.19 09:59
Оценка:
Здравствуйте, Marty, Вы писали:

M>В итоге вроде бы решил самым простым способом, без изысков

M>Хочу:
M>
M>сonstexpr uintptr_t a = 140721923966320;
M>cout<<a;
M>


В новых стандартах можно писать с изысками:
constexpr uintptr_t a = 140'721'923'966'320;
И каждый день — без права на ошибку...
Re[3]: Препроцессор:Как правильно задавать константы/литералы определенного интг
От: Sergey_BG Россия  
Дата: 17.04.19 10:49
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>В MSVC компилируется.


Интересно это их специальная политика, чтоб ухудшить переносимость, или же они об удобстве беспокоятся.
Сергей
Re[4]: Препроцессор:Как правильно задавать константы/литералы определенного интг
От: _NN_ www.nemerleweb.com
Дата: 17.04.19 11:06
Оценка:
Здравствуйте, Sergey_BG, Вы писали:

S_B>Здравствуйте, _NN_, Вы писали:


_NN>>В MSVC компилируется.


S_B>Интересно это их специальная политика, чтоб ухудшить переносимость, или же они об удобстве беспокоятся.


Или предсказывают светлое будущее как было с typename
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Препроцессор:Как правильно задавать константы/литералы определенного интг
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 18.04.19 20:10
Оценка:
Здравствуйте, watchmaker, Вы писали:

Спасибо за ликбез
Маньяк Робокряк колесит по городу
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.