2013-06-17 13 views
6

Sto provando a definire il mio tipo di dati (chiamato sfloat) simile a un float, ma utilizza un numero diverso di bit mantissa e bit esponenziali per adattarsi meglio alla mia gamma di dati e alla precisione. L'obiettivo è definire un nuovo tipo di dati che possa sostituire il float in applicazioni già esistenti. Tutto sta funzionando finora, tranne che sono stato in grado di ignorare o definire l'operatore unsigned tale cheIndicatore 'unsigned` overloader per classi

unsigned sfloat(3.141527) 

sarebbero ritornati la versione senza segno di questa classe, usfloat(3.141527).

Sembra che il unsigned specificatore forza essere in grado di essere sovraccaricato dal VS IntelliSense non si lamenta nel file di intestazione:

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

Ma non funziona in dichiarazione e l'inizializzazione:

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

Non so nemmeno se è possibile farlo in C++ e sono curioso di sapere se qualcuno lo ha già fatto prima?

+1

'unsigned' non è un qualificatore come' const' o 'volatile'.È una parte inseparabile di un nome di tipo, come 'short' o' long'. 'unsigned' da solo è un sinonimo di' unsigned int', quindi 'operator unsigned()' è solo un operatore per il cast di 'unsigned int'. – Oktalist

risposta

7

A causa di C++ default-int per la firma, operator unsigned() è solo una sintassi sintattica per operator unsigned int(). I tipi definiti dall'utente non possono essere dichiarati signed o unsigned.

3

Non esiste un modo diretto per eseguire ciò che si sta tentando di fare. Come @Angew menzionato nella sua risposta, unsigned non può essere applicato a tipi definiti dall'utente.

D'altra parte, è possibile simulare questo tipo definendo i tipi denominati sfloat e unsigned_sfloat che hanno definito le conversioni tra di loro. È quindi possibile scrivere

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

e quindi definire un operatore di conversione come

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

Questo ti dà qualcosa sintatticamente vicino a quello che si vuole e lavora intorno al fatto che la lingua non consente di utilizzare il unsigned parola chiave per modificare un tipo personalizzato.

Spero che questo aiuti!

0

Provare quanto segue:

template<typename T> 
struct Unsigned; 

e usarlo come:

Unsigned<sfloat> usfloat 

Ora, è necessario specializzarsi Unsigned per il tuo tipo Float, ma questo dovrebbe comunicare "è una versione senza segno di Float "leggermente migliore di un tipo unsigned_sfloat. Mi preoccuperei solo di questo se tu costruisci un'intera libreria di questi tipi che potresti voler collegare Unsigned<> a, comunque.

1

Si potrebbe prendere in giro qualcosa di simile con i modelli:

#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

Questo appena * rileva * se il float non è firmato, piuttosto che dare un modo di modificare la classe da firmare o non firmata? – templatetypedef

+0

@templatetypedef A causa della specializzazione, è possibile avere implementazioni completamente diverse delle versioni firmate e non firmate (se lo si desidera). Potresti anche estrarre funzionalità comuni, ovviamente. – jerry

+0

@ jerry- Ah, non importa. Hai modificato il post per menzionare che le specializzazioni includono anche il corpo completo delle implementazioni. Al momento in cui ho postato il commento, hai appena avuto la costante 'isSigned' nelle specializzazioni. – templatetypedef