Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> определение знакового типа с помощью template 
V
    Опции темы
Ivan.
Дата 30.1.2015, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Доброе время суток.
подскажите, требуется определить знаковый или без знаковый тип.
один из вариантов решения - это template
Код

template <class T> struct SignDetection {enum {IsSigned = false};};
template <class T> struct SignDetection<const T> {enum {IsSigned = SignDetection<T>::IsSigned};};
template <> struct SignDetection<s8> {enum {IsSigned = true};};
template <> struct SignDetection<s16> {enum {IsSigned = true};};
template <> struct SignDetection<s32> {enum {IsSigned = true};};
template <> struct SignDetection<s64> {enum {IsSigned = true};};
...
if (SignDetection<T>::IsSigned){...}

все базовые знаковые типы возвращают true, а все прочие типы возвращают false, но что делать, если тип рожден от базового знакового типа? например:
Код

enum MyEnum: s8{...}

этот тип не попадает под специализированный шаблон и возвращает false.
конечно можно при объявлении очередного типа описывать шаблон SignDetection, но это не удобно и рано или поздно забудешь его описать, а потом придется ехать куда нибудь в Ямал перепрошивать контроллер.
можно ли как нибудь написать обобщенный шаблон для таких случаев?

Добавлено через 5 минут и 33 секунды
чуть промахнулся разделом, можно переместить в C/C++: Общие вопросы


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
tzirechnoy
Дата 30.1.2015, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 2
Всего: 16



#include <limits>, далее по обстоятельствам.
PM MAIL   Вверх
Ivan.
Дата 30.1.2015, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



не вижу решения


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
xvr
Дата 2.2.2015, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



А по старинке не подойдет?
Код

template <class T> 
struct SignDetection {
 enum {IsSigned = T(~0) < T(0) };
};


PM MAIL   Вверх
baldina
Дата 2.2.2015, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



во-первых, есть std::is_signed в type_traits
во-вторых, MyEnum не является арифметическим типом, и не может быть знаковым или беззнаковым

PM MAIL   Вверх
Ivan.
Дата 19.2.2015, 08:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Цитата(baldina @  2.2.2015,  16:45 Найти цитируемый пост)
во-первых, есть std::is_signed в type_traits

в gcc такого не нашел
Цитата(baldina @  2.2.2015,  16:45 Найти цитируемый пост)
во-вторых, MyEnum не является арифметическим типом, и не может быть знаковым или беззнаковым

Информация устаревшая, смотри C++11,14

Добавлено через 9 минут и 1 секунду
Цитата(xvr @  2.2.2015,  14:51 Найти цитируемый пост)
А по старинке не подойдет?
template <class T> struct SignDetection { enum {IsSigned = T(~0) < T(0) };};

аналогичный способ у меня был реализован, к нему и вернемся
Код

template<class T> struct SignDetection {enum {IsSigned = static_cast<T>(-1) < static_cast<T>(0)};};
template<class T> struct SignDetection<const T> {enum {IsSigned = SignDetection<T>::IsSigned};};

а для объектов не имеющих операторов сравнения и конструктора от int придется писать специализированный шаблон
Код

template<> struct SignDetection<MyObj> {enum {IsSigned = false};};



--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
baldina
Дата 19.2.2015, 12:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(Ivan. @  19.2.2015,  08:57 Найти цитируемый пост)
в gcc такого не нашел

Цитата(Ivan. @  19.2.2015,  08:57 Найти цитируемый пост)
Информация устаревшая, смотри C++11,14

стандарт говорит
Цитата

3.9.1
7. Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively
called integral types*. A synonym for integral type is integer type.
...
*Therefore, enumerations (7.2) are not integral;

а вот говорит gcc, C++14: http://ideone.com/zgVldn

если у вас более свежая информация, дайте пруфлинк

Код

enum fruit : int {apple,orange,banana};
по-вашему fruit - знаковый тип? какого знака orange?

Это сообщение отредактировал(а) baldina - 19.2.2015, 12:30
PM MAIL   Вверх
sQu1rr
Дата 19.2.2015, 16:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 597
Регистрация: 11.11.2008
Где: london

Репутация: 3
Всего: 13



Можете использовать underlying_type что бы вытянуть тип енума и уже его проверять на знак
http://en.cppreference.com/w/cpp/types/underlying_type
PM MAIL Skype GTalk   Вверх
baldina
Дата 19.2.2015, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



да, можно. только ничего не решает, т.к. 
1. сам енум остается нечисловым типом, у которого нет понятия знака
2. в случае знакового родителя невозможно определить, какого знака элементы енума. возможно только какого они могут быть

просто я не понимаю зачем может потребоваться определение знака енума, т.к. это абстрактное множество, а нумерация его элементов это лишь реализация. оптимизация? допустим... но придумать место этой оптимизации я не смог. типичное использование underlying_type - определение размера и кастование к базовому типу для передачи туда, где нет енумов, а причем тут знак...
PM MAIL   Вверх
Ivan.
Дата 19.2.2015, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



то что шаблоны is_signed и is_unsigned от enum возвращают false - это не значит, что enum не является не тем не другим, это значит, что эти шаблоны его так определяют. это всего лишь один из методов определения знака написанный человеком.
enum это замена целочисленных констант словами.
пример: 
Код
enum MyEnum: signed {A, B};
MyEnum a = A;
MyEnum b = B;

мы можем сравнить a < b ? и как будет выполнено сравнение? со знаком или без?
а если мы решим произвести умножение
Код
int c = 10; c *= b;
 умножение будет выполнено со знаком или без? это разные ассемблерные команды.
Код
enum MyEnum1: signed char {A1 = -1}; //OK
enum MyEnum2: unsigned char {A2 = -1}; //Error
enum MyEnum3: signed char {A3 = 255}; //Error
enum MyEnum4: unsigned char {A4 = 255}; //OK
long a = A1; //a = -1 (0xFFFFFFFF)

и самое интересное:
Код
unsigned int a = 10; if (a < A1){...}

Warning    1    comparison between signed and unsigned integer expressions
это значит, что A1 является знаковым

Это сообщение отредактировал(а) Ivan. - 20.2.2015, 09:25


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
baldina
Дата 20.2.2015, 01:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Ivan., все, что вы привели, замечательно, но на вопрос не отвечает. причем тут enum? в ваших примерах это могут быть просто константы: главные свойства enum - ограниченноcть множества значений и их общность (единый тип) - не используются.
обсуждать технические нюансы решений, прикладной смысл которых не ясен,  имхо пустое занятие (именно в этот момент возникает столь нелюбимый топикстартерами вопрос "зачем вам это" ).
можно, конечно, придумать множество изощренных способов использования перечислений, только от них обычно больше головной боли, чем пользы. и практически всегда можно заменить более простыми конструкциями

ЗЫ.
Цитата(Ivan. @  19.2.2015,  22:30 Найти цитируемый пост)
это значит, что A1 является знаковым 

изучаете язык по сообщениям компилятора? ну-ну...


Это сообщение отредактировал(а) baldina - 20.2.2015, 01:34
PM MAIL   Вверх
Lukkoye
Дата 20.2.2015, 03:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 23.3.2013

Репутация: 1
Всего: 1



Обычный enum - сахар над int.
Он - знаковый.

Остальные - наследуют все свойства тех типов, от которых они унаследованы.

Цитата(baldina @  19.2.2015,  12:21 Найти цитируемый пост)
стандарт говорит

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

(хотя енум на самом деле не является арифметическим типом, согласно std)
Код

All fundamental arithmetic types, along with all their aliases (like those in cstdint), 
are considered arithmetic types by this class,
including their const and volatile qualified variants.

Enums are not considered arithmetic types in C++ (see is_enum).



Цитата(baldina @  19.2.2015,  12:21 Найти цитируемый пост)
по-вашему fruit - знаковый тип? какого знака orange?


Да, fruit  знаковый, поскольку унаследовал все свойства интегрального типа, от которого он образован.

orange - положительный, поскольку по дефолту первый элемент - ноль, а остальные инкриментируются.

Цитата(baldina @  20.2.2015,  01:32 Найти цитируемый пост)
 все, что вы привели, замечательно, но на вопрос не отвечает. причем тут enum?


При том, что такой enum реализует отношение "является", когда наследуется от интегрального типа.
Он наследует его свойства, его особенности, если хотите.

Более того: в операциях с енум этот фактор учитывается.
Необходимо учитывать ограниченность возможных значений такого енума, например.
Из этой необходимости прямо вытекает необходимость учитывать знаковость енума:

Код

// ok
enum example: unsigned char { one = 200 };

// error: enumerator value 200 is too large for underlying type ‘signed char’
enum example: signed char { one = 200 };


Код

enum example: unsigned char { one = 200 };

// gcc был установлен ключик -fpermissive, что бы не бухтел на эксперимент
example val = one + one;
    
std::cout << "value = " << val <<'\n';  // value = 144 переполнение


Фактически, енум отличается от базового типа, от которого он унаследовался 
только возможностью задавать именованные константы времени компиляции.

Важно понимать, что защита приведения типов, 
а так же запрет арифметических операций - это искусственные ограничения. 
А сам енум по сути - всего лишь сахар над интегральными типами. 
Предназначение которого - типизированные, именованные  константы гарантированно времени компиляции.



Это сообщение отредактировал(а) Lukkoye - 20.2.2015, 03:23
PM MAIL   Вверх
Ivan.
Дата 20.2.2015, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Цитата(baldina @  20.2.2015,  01:32 Найти цитируемый пост)
можно, конечно, придумать множество изощренных способов использования перечислений, только от них обычно больше головной боли, чем пользы. и практически всегда можно заменить более простыми конструкциями

от еnum очень много пользы:
1. наглядность (RED, GREEN, BLUE) (REQUEST, RESPONSE) (COMMAND1, ..., COMMAND5)
2. невозможность присвоить типу Color значение REQUEST
3. автоинкрементор
4. защита в switch от пропущенного case при отсутствии default. если в енум добавили новый аргумент (COMMAND6) то все switch попросят добавить обработку данного значения (опять же если отсутствует default)
5. специализация шаблонов template<> struct TypeName {constexpr static const char name[] = "Цвет";};
6. декларация enum MyEnum; (библиотека будет знать, что когда нибуть будет описан MyEnum)
и множество других приимуществ
недостатки:
1. нельзя наследовать енум от другого енума и продолжить автоинкрементор enum ExtColor: Color {};
2. невозможность проводить арифметические действия: color = RED + GREEN; но это скорее польза, а не недостаток. защита от создания несуществующего значения енума.
приведи мне хоть один реальный недостаток енумов

Зачем мне знаковый енум?
enum SensorChannel: signed {NO_SENSOR = -1, SENSOR1, SENSOR2};
библиотека, где продекларирован enum SensorChannel: signed; не знает количество датчиков, которое будет описано в проекте, но точно знает, что отрицательное значение означает отсутствие канала датчика.

Зачем мне определять знак енума?
честно говоря не хочу сейчас распинаться описывая свою задачу. надо, значит надо.

PS. тема давно закрыта и решение найдено


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1367 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.