2013-06-17 15 views
6

Próbuję zdefiniować własny typ danych (o nazwie sfloat), który jest podobny do float, ale używa innej liczby bitów mantysy i bitów wykładniczych, aby lepiej pasowały do ​​mojego zakresu danych i precyzji. Celem jest zdefiniowanie nowego typu danych, który może zastąpić zmienną w już istniejących aplikacjach. Wszystko działa do tej pory, oprócz tego, że nie byłem w stanie zastąpić lub zdefiniować operator unsigned takie, żePrzeciążenie typu "unsigned" dla klas

unsigned sfloat(3.141527) 

wróci niepodpisany wersję tej klasy, usfloat(3.141527).

Wydaje się specyfikatorem unsignedpotęga móc być przeciążony od VS intellisense nie narzeka w pliku nagłówka:

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

Ale to nie działa w deklaracji i inicjalizacji:

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

Nie wiem nawet, czy można to zrobić w C++, i jestem ciekawy, czy ktoś to zrobił wcześniej?

+1

'unsigned' nie jest kwalifikator jak' const' lub 'volatile'.Jest nieodłączną częścią nazwy typu, np. 'Short' lub' long'. 'unsigned' samo w sobie jest synonimem' unsigned int', więc 'operator unsigned()' jest po prostu operatorem do rzutowania na 'unsigned int'. – Oktalist

Odpowiedz

7

Ze względu na domyślną int C++ dla sygnatury, operator unsigned() jest po prostu skrótem syntaktycznym dla operator unsigned int(). Zdefiniowane przez użytkownika typy nie mogą być zadeklarowane jako signed lub unsigned.

3

Nie ma bezpośredniego sposobu na osiągnięcie tego, co próbujesz zrobić. Jak wspomina @Angew w swojej odpowiedzi, unsigned nie może być stosowany do typów zdefiniowanych przez użytkownika.

Z drugiej strony można to zmylić, definiując typy o nazwach sfloat i unsigned_sfloat, w których zdefiniowano konwersje między nimi. Następnie można napisać

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

a następnie zdefiniować operator konwersji jako

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

To daje coś składniowo blisko tego, co chcesz i pracuje wokół faktu, że język nie pozwala używać unsigned słowo kluczowe do modyfikacji typu niestandardowego.

Mam nadzieję, że to pomoże!

0

Spróbuj wykonać następujące czynności:

template<typename T> 
struct Unsigned; 

i używać go lubię:

Unsigned<sfloat> usfloat 

Teraz trzeba specjalizować Unsigned dla danego typu Float, ale to powinno komunikować „jest niepodpisany wersja Float "nieco lepszy niż typ unsigned_sfloat. Mógłbym to tylko zawracać sobie głowę, jeśli budujesz całą bibliotekę tego typu, do której możesz jednak dołączyć.

1

Można wyśmiewać coś takiego z szablonów:

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

Czy to nie * wykrywa *, czy liczba zmiennoprzecinkowa jest niepodpisana, czy nie daje możliwości modyfikacji klasy, która ma być podpisana lub niepodpisana? – templatetypedef

+0

@templatetypedef Ze względu na specjalizację, możesz mieć zupełnie różne implementacje podpisanych i niepodpisanych wersji (jeśli chcesz). Oczywiście można również wyciągnąć wspólną funkcjonalność. – jerry

+0

@ jerry- Ah, nieważne. Edytowałeś post, aby wspomnieć, że specjalizacje obejmują także cały zestaw implementacji. W momencie opublikowania komentarza po prostu miałeś stałą "isSigned" w specjalizacjach. – templatetypedef

Powiązane problemy