2010-12-12 19 views
14

Farklı tamsayı türleri arasında dönüştürmek istediğiniz, en iyi sözdizimi boost::numeric_cast<>() kullanmaktır görünüyor:kullanma boost :: numeric_cast <>

int y = 99999; 
short x = boost::numeric_cast<short>(y); // will throw an exception if y is too large 

Bunu hiç kullanılmamış; ancak sözdizimi oldukça basit, bu yüzden her şey yolunda.

Şimdi biraz daha gelişmiş bir şey yapmak istediğimi varsayalım: bir istisna atmak yerine, hedef türün (doygunluk) min veya maksimum değerini döndürmesini istiyorum. Bunu ifade etmenin bir yolunu anlayamadım, ancak documentation bunun mümkün olduğunu (muhtemelen RawConverter ilkesini kullanarak) önerir. Ben ile gelebilir tek şey çirkin aşağıdadır:

short x = numeric_cast<short>(max(min(y, SHORT_MAX), SHORT_MIN); 

Peki nasıl boost en numeric_cast kullanarak bir "cast doyurarak" ifade edebilir

?

cevap

15

Muhtemelen böyle bir şey yapabileceğini:

#include <limits> 

template<typename Target, typename Source> 
Target saturation_cast(Source src) { 
    try { 
     return boost::numeric_cast<Target>(src); 
    } 
    catch (const boost::negative_overflow &e) { 
     return std::numeric_limits<Target>::lowest(); 
     /* Or, before C++11: 
     if (std::numeric_limits<Target>::is_integer) 
     return std::numeric_limits<Target>::min(); 
     else 
     return -std::numeric_limits<Target>::max(); 
     */ 
    } 
    catch (const boost::positive_overflow &e) { 
     return std::numeric_limits<Target>::max(); 
    } 
} 

(ayrıca/+ inf -inf geri dönebilirler o hata şeklini destekler türleri için).

Böylelikle Boost'un numeric_cast değerine izin verdiğinizde, değerin sınırların dışına çıkıp çıkmadığını belirler ve buna göre tepki verebilir.

+0

İstisna bağlı :(Bazı projeler C++ istisnası kullanmaz, bunu hatırlamak iyi .. BTW: İmzalı/imzasız bir döküm için hala çalışır mı? – Kos

+3

@Kos: Bir proje tüm dil özelliklerini kullanmıyorsa, Bu projenin problemi: Kimse, bazı özellikleri kullanmayan bir dil için kod yazmamalı çünkü bir başkası bu özellikten hoşlanmayabilir .. – Puppy

+0

İstisnalar, tüm avantajlarının yanı sıra, kontrol akışını daha karmaşık hale getiriyor ve aynı zamanda genel giderler de getiriyor. "kodlama standardı" denir, buna "kodlama standardı" denir. Birçok (hepsi değil, ofc) C++ projelerinin istisnasız var olmak için iyi nedenleri vardır ve bunlar istisna desteği olmadan derlenirler. – Kos

2

Hm ... Yukarıdaki eserler ise, genel bir çözüm muhtemelen bir şey gibi yapmak olacaktır: Bunun doğru ... Neyse, kavram var var

template<typename TypeFrom, typename TypeTo> 
TypeTo saturated_cast(TypeFrom value) { 
    TypeTo valueMin = std::numeric_limits<TypeTo>::min(); 
    TypeTo valueMax = std::numeric_limits<TypeTo>::max(); 
    return boost::numeric_cast<TypeTo>(std::max(std::min(value,valueMax),valueMin)); 
} 

Hope :)

.... BTW: Burada static_cast'u kullanabileceğinizi düşünüyorum, çünkü sınırlamayı gerçekleştirdikten sonra artık aralığı taşamazsınız, bu nedenle numeric_cast ek kontrolüne ihtiyacınız yoktur.

+1

aynı konuyu GregHill, karşılaştırmadan önce yer almalıdır, aksi takdirde "numeric_cast" işlevini kullanmanın yararı yoktur, çünkü aralığın doğru olduğunu kontrol etmek için yine de aynı karşılaştırmaları gerçekleştirir. Ayrıca, std :: min' ve 'std :: max' yalnızca aynı türden iki argüman için çağrılabilir, bu kod derlenmez. –

İlgili konular