Pull to refresh

Comments 29

а что возвращает sizeof в таком случае? хотя, при правильной постановке дела это не так уж важно.

А вообще, не вижу необходимости переопределять стандартные типы
sizeof по идее должен вернуть sizeof от приватной переменной _value. Переопределение типов может и дело вкуса, но у меня вот такой вот вкус, понравились некоторые моменты написания кода на C#, хотя я и предпочтаю С++.
Но «по идее» не значит «по стандарту» — никто этого не гарантирует. Еще, кстати, по стандарту, вы не можете теперь копировать объекты Double, Char, Bool с помощью memcpy(), сохранять/загружать их побайтно из файлов и не можете передавать их в функции с переменным количеством аргументов.
Возможно сможет с выходом следующего стандарта. Там расширили ограничения для POD-типов. Им теперь можно иметь конструкторы и прочее (разумеется, с ограничениями, но уже можно), но надо вникать.
Правильная постановка дела доступна не на любом компиляторе :)

А преимуществ переопределения тоже не увидел.
Батюшки :) char и double имхо переопределять ни к чему, но если вам это реально необходимо, может стоит пиать на C#, Java?
С#/Java все же несколько уступают по производительности ЯП компилируемым в нативный код, не берусь оценить насколько. А для меня производительность — это ОЧЕНЬ важный показатель… хотя, как уже писал выше, писать код на C# к примеру мне приятно, мозг меньше напрягается:)
Оптимизировать надо там, где тормозит, а брать C++ потому, что он «быстрее в целом» несколько странно. Разве что у вас вся программа везде к скорости критична.

П.С. Сам люблю Си++
UFO just landed and posted this here
вообще, я высказался не совсем точно, C#/Java тоже можно в нативный код скомпилировать, и C++ под виртуальной машиной запустить, еще и со сборщиком мусора:) но нативный код, т.е. код исполняемый процессором в общем случае быстрее кода исполняемого виртуальной машиной, тут думаю доказательств не нужно.
UFO just landed and posted this here
Один вопрос — зачем?

Переопределение базовых типов делается как минимум в двух случаюх
1. Краткость записи
2. Кроссплатформа

С первым случаем все ясно, во втором случае определяются единые имена для фиксированных размеров, например int на разных плафтормах занимает разное кол-во байт, следовательно делают определение int32 с помощью #ifdef дабы получить фиксированные типы на всех платформах.

В вашем же случае не видно мотивации, плюс дикие затраты по написанию этих классов, которые абсолютно не нужны :)
Извиняюсь за цитирование поста, но:

«Таким образом, можно работать с простейшими типами как с объектами, повысить удобочитаемость кода, иметь больше контроля над тем что происходит в программе(например, для подсчета количества умножений, выполняемых над типом double достаточно поместить счетчик в перегруженный оператор).»

как вам такие задачи?)))
а чем такая задача плоха? сейчас просто занимаюсь написанием трассировщика лучей, планирую реализовать фотореалистичный рендеринг. и планирую оптимизировать, учитывая каждый такт процессорного времени…
а я и не говорю что плоха. Хороша. Просто я удивляюсь комментатору, который не осилил прочитать пост до конца
насколько я понимаю, для современного процессора важно не столько количество операций умножения, сколько возможность правильно их распараллелить, а еще удачно предсказать ветвления.
И, самое критичное — работа с памятью, тут разве что хуже получится
Кроме того, если вам так дико хочется внедрять такие классы, дык пишите шаблонами.
template <class T> class Number {… };
class Char: public Number<char> {… };

template <class T> struct SignedUnsigned { enum { isSigned = 0; } };
template <> struct SignedUnsigned<unsigned int> { enum { isSigned = 1; } };
template <> struct SignedUnsigned<unsigned char> { enum { isSigned = 1; } };

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

bool IsSigned() { return SignedUnsigned<T>::isSigned; }

и потом
typedef Number<int> Integer;
typedef Number<unsigned int> UnisgnedInteger;

Но в целом, это ненужные извращения ;-) Если вам так не хватает вспомогательных функций, напишите утилитарный шаблон, и пользуйте его

template <class T> class Utility { bool isSigned() {… }; bool isPositive() {… }; };

Это в разы проще и полезнее, чем ваять извращения ;) К тому же такие утилитарные шаблоны есть уже готовые.
Тогда позднее связывание отдыхает.
Например, я хочу чтобы программа могла «на лету» без перезагрузки переключаться между уровнями отладки. Или для разных плагинов иметь разные уровни отладки. Для веб-сервера это очень хорошо.
Вы о чем? Какое позднее? Судя по описанию выше у вас нет ни единой виртуальной функции, какое такое подзднее связывание? В этом плане ваши типы не должны отличатся от базовых, и они таки не будут отличаться с шаблонами в таком контексте.
А, да, точно.
Это у автора нет. А у меня бы были =)
Ну, тут меня наверное сложно понять:))

1. Краткость записи
2. Кроссплатформа

Да, и для этого тоже.

3. Красота кода (тема для отдельного поста)
4. Расширябельность
5. Тотальный контроль

Примеров можно привести много. Я просто думаю, «а вдруг...» Захочется мне например, или сочту нужным, операцию умножения чисел
типа double переопределить как

Double result = (float) a * (float) b

либо переписать сам на ассемблере, либо таблички какие нибудь задействовать, либо еще что:)

Вот не знаю, надо мне и все:)
Можно сказать одним предложение «вы просто не знаете, чем заняться».
По пунктам легко опровергнуть все ваши слабые доводы :)

3. Имхо, стандартные типы float, int, char куда как «красивее» (если это понятие вообще применимо).
4. Стандартные типы расширябельнее некуда. Куда вы собрались расширять ваш Double или Int?
5. Контроль за стандартными типа полный изначально! И в stdlib есть полная поддерка этих типов для свех необходимых операций.

Еще раз укажу вам ваши же слова: "__Вот не знаю__, надо мне и все:)"
Вы просто не знаете, что хотите. На украине есть поговорка (никаких личностей): «За дурною головою і ногам нема покою».

Теперь касательно цитаты выше: «Таким образом, можно работать с простейшими типами как с объектами, повысить удобочитаемость кода, иметь больше контроля над тем что происходит в программе(например, для подсчета количества умножений, выполняемых над типом double достаточно поместить счетчик в перегруженный оператор).»

1. Зачем типам вести себя, как объекты? Это абсолютно без надобности.
2. Удобочитаемость со стандартными типами выше. Любой программист увидев строчку double f; будет на 100% уверен в том, что представляет собой f. Увидев же строку Double f программист полезет в документацию, что бы убедиться, что автора этого самого Double не напортачил лишнего и не извратил стандартный тип «удивительными» элементами.
3. Контроль над стандартными типами выше любого объекта. Опять же, int — это всегда int, double — всегда double. Получая же ваш Double* я абсолютно не уверен, что это именно Double*, а не какой-нибудь наследник или еще что-нибудь подобное.

Нет ни одной объективной причины делать обертки для типов (ну кроме «мне так хочется»). В любом случае вы теряете много времени для сохранения совместимости и переносимости и взамен не получаете ничего такого, чего нельзя сделать со стандартными типами.
Написать обертки поверх стандартных типов можно, только вот встроить это в существующие стандартные (да и не только стандартные) библиотеки не представляется реальным — костыли делать надоест.
Java стиль, совершенно не нужный в C++. Кстати, если посмотрите можете открыть для себя много нового.
в Java, к сожалению, есть boxing и unboxing на уровне языка, что существенно все упрощает. Не уверен что это полностью эмулируется на сях перегрузкой операторов.
Вполне возможно.
Таким образом, можно работать с простейшими типами как с объектами, повысить удобочитаемость кода, иметь больше контроля над тем что происходит в программе(например, для подсчета количества умножений, выполняемых над типом double достаточно поместить счетчик в перегруженный оператор).


Я так понимаю, данный подход дает два бонуса:

1. Удобочитаемость кода.

Тут нужен пример. Мне отсюда совершенно не видно как используя вместо UINT32 класс Int можно повысить читаемость кода. Вполне возможно, далеко сижу. Примеры в студию.

2. Очень трудно придумать практическую задачу, где потребовалось бы узнать количество умножений double в программе. В конце концов для этого всегда можно переопределить глобальный operator*. Какие-нибудь другие примеры кроме подсчета умножений про контроль будут?

ИМХО, никто этого не делает по причине бесполезности. Тоесть делать так — это добавлять в проект некий код, который не делает ничего. А времени на нанисание, поддержку и сопровождение требудет.

Это я без учета нюансов разницы поведения POD типов и классов, совместимости с существующим кодом включая шаблонный и прочих мелочей которые могут всплыть. А могут и не всплыть.
UFO just landed and posted this here
Плюсов не видно. А из минусов такого подхода: со встроенными типами сторонние библиотеки умеют работать «из коробки», а для собственных типов придется каждый раз дописывать дополнительный код-адаптер.

Пример:
double d;
std::cin >> d;
boost::archive::binary_oarchive a;
a << d;

А класс Double для такого пришлось бы «допиливать».
Sign up to leave a comment.

Articles