Спецификатор перегрузки `unsigned` для классов

Я пытаюсь определить свой собственный тип данных (называемый sfloat), который похож на число с плавающей точкой, но использует другое число мантиссы биты и экспоненциальные биты, чтобы лучше соответствовать диапазону данных и точности. Цель состоит в том, чтобы определить новый тип данных, который может заменить число с плавающей точкой в ​​уже существующих приложениях. Пока что все работает, за исключением того, что я не смог переопределить или определить оператор unsigned так, чтобы

unsigned sfloat(3.141527)

вернет неподписанную версию этого класса, usfloat(3.141527).

Похоже, что спецификатор unsigned может быть перегруженным, поскольку VS intellisense не жалуется в заголовочный файл:

sfloat::sfloat(float f) { m_data = get16bit(f); }
operator unsigned() { /*Do stuff here */ };

Но это не работает при объявлении и инициализации:

unsigned sfloat myPi= 3.141527; // Error: expected a ';'

Я даже не знаю, возможно ли это сделать в C ++, и мне любопытно, кто-нибудь делал это раньше?

c++
6 голосов | спросил John Phu Nguyen 17 J0000006Europe/Moscow 2013, 22:36:16

4 ответа


0

Из-за C ++ default-int для подписи operator unsigned () является всего лишь синтаксическим сокращением для operator unsigned int (). Пользовательские типы не могут быть объявлены signed или unsigned.

ответил Angew 17 J0000006Europe/Moscow 2013, 22:38:16
0

Нет прямого способа выполнить то, что вы пытаетесь сделать. Как отметил @Angew в своем ответе, unsigned нельзя применять к пользовательским типам.

С другой стороны, вы можете подделать это, определив типы с именами sfloat и unsigned_sfloat, для которых определены преобразования. Вы можете написать

unsigned_sfloat x(137.0f); // Close enough. ^_^

А затем определите оператор преобразования как

operator unsigned_sfloat() {
    ... implementation here ...
}

Это дает вам что-то синтаксически близкое к тому, что вы хотите, и работает вокруг факта, что язык не позволяет вам использовать ключевое слово unsigned изменить пользовательский тип.

Надеюсь, это поможет!

ответил templatetypedef 17 J0000006Europe/Moscow 2013, 22:40:36
0

Вы можете сделать что-то подобное с шаблонами:

#include <type_traits>

template <typename T = int>
class myfloat
{
    static_assert(std::is_same<T, int>::value, "myfloat should only be instantiated on \"signed\" and \"unsigned\" ints");

    const bool isSigned = true;

    // the rest of the signed implementation  
};

template <>
class myfloat<unsigned>
{
    const bool isSigned = false;

    // the rest of the unsigned implementation  
};

int main()
{
    myfloat<> a;           // signed  
    myfloat<signed> b;     // signed  
    myfloat<unsigned> c;   // unsigned  

    // myfloat<float> d; // <-- compile error

    return 0;
}
ответил jerry 17 J0000006Europe/Moscow 2013, 22:53:19
0

Попробуйте сделать следующее:

template<typename T>
struct Unsigned;

и используйте его так:

Unsigned<sfloat> usfloat

Теперь вам нужно специализировать Unsigned для вашего типа Float, но это должно сообщать "это неподписанная версия Float", немного лучше, чем unsigned_sfloat тип. Я бы беспокоился об этом только в том случае, если вы собираете целую библиотеку таких типов, вы, возможно, захотите прикрепить Unsigned<>, однако.

ответил Yakk - Adam Nevraumont 17 J0000006Europe/Moscow 2013, 22:48:28

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132