devo funzioni per convertire diversi tipi aritmetici per mezzo precisione floating point (solo un uint16_t
al livello più basso) e hanno funzioni differenti per interi e galleggianti tipi di origine punto, utilizzando SFINAE e std::enable_if
:SFINAE differenziazione tra firmato e unsigned
template<typename T>
uint16_t to_half(typename std::enable_if<
std::is_floating_point<T>::value,T>::type value)
{
//float to half conversion
}
template<typename T>
uint16_t to_half(typename std::enable_if<
std::is_integral<T>::value,T>::type value)
{
//int to half conversion
}
Questi sono chiamati internamente da un costruttore su modelli universali per esemplificazione esplicito:
template<typename T>
half::half(T rhs)
: data_(detail::conversion::to_half<T>(rhs))
{
}
Questo compila e funziona anche bene. Ora cerco di distinguere tra numeri interi con e senza segno, sostituendo la seconda funzione, con le due funzioni:
template<typename T>
uint16_t to_half(typename std::enable_if<std::is_integral<T>::value &&
std::is_signed<T>::value,T>::type value)
{
//signed to half conversion
}
template<typename T>
uint16_t to_half(typename std::enable_if<std::is_integral<T>::value &&
std::is_unsigned<T>::value,T>::type value)
{
//unsigned to half conversion
}
Ma una volta che provo a compilare questo VS2010 mi dà
errore C2995:
"uint16_t math::detail::conversion::to_half(std::enable_if<std::tr1::is_integral<_Ty>::value && std::tr1::is_signed<_Ty>::value, T>::type)"
: la funzione modello già definito.
Quindi sembra che non possa disambiguare tra i due modelli, ma ovviamente non ha avuto problemi con la versione integrale a fianco della versione in virgola mobile.
Ma dal momento che non sono tanto un mago di modelli, potrei semplicemente mancare qualcosa di ovvio qui (o forse dovrebbe funzionare davvero ed è solo un bug VS2010). Quindi, perché non funziona e come può essere fatto funzionare con il minor numero possibile di programmazioni possibili e nei limiti delle funzionalità solo standard (se possibile)?
Non è chiaro che 'is_signed' /' is_unsigned' si escludono a vicenda (ciao 'char'?). Prova a fare in modo che la seconda versione dica '! Std :: is_signed :: value'. –
Puoi provare a usare 'std :: is_signed :: value' per uno dei membri e'! Std :: is_signed :: value' per l'altro? Questo è solo per assicurarsi che non ci sia solo un tipo che ha impostazioni incoerenti per 'is_signed' e' is_unsigned'. –
@KerrekSB e Dietmar Hah, l'ha fatto! Non posso credere che sia stato così facile. Se qualcuno lo aggiunge come risposta, lo accetto. –