numeric_cast

18 listopada 2008

Korzystając z wzorca numeric_limits, o którym wspomniałem w poprzedniej notce i informacjach o min/max wartości danego typu numerycznego, można w bardzo łatwy sposób stworzyć sobie bezpieczny, odporny na underflow/overflow, „operator” – wzorzec do konwersji wartości liczbowych pomiędzy poszczególnymi typami numerycznymi.

template <typename TargetType, typename SourceType>
inline TargetType numeric_cast(SourceType arg) {
 
	if (arg < std::numeric_limits<TargetType>::min())
		throw std::underflow_error("bad numeric cast");
 
	if (arg > std::numeric_limits<TargetType>::max())
		throw std::overflow_error("bad numeric cast");
 
	return static_cast<TargetType>(arg);
 
}

Drugi typ argumentu wzorca można pominąć, zostanie on wydedukowany przez kompilator na podstawie typu argumentu przekazanego do funkcji, więc konstrukcja ta przyjmuje prostą postać podobną do wbudowanych operatorów rzutowania:

try {
 
	char c			= 100;
	int i			= -129;
	unsigned int ui	= 12345;
	long long l		= 453232;
 
	c = numeric_cast<char>(i);		// overflow_error
	i = numeric_cast<int>(c);
	i = numeric_cast<int>(ui);		// underflow_error
	l = numeric_cast<long long>(i);
 
} catch (const std::underflow_error& e) {
	std::cout << "underflow_error: " << e.what() << endl;
 
} catch (const std::overflow_error& e) {
	std::cout << "overflow_error: " << e.what() << endl;
}

W rzeczywistości konstrukcja takiego „operatora” nie jest taka prosta jak się może wydawać i powyższy program nie zadziała tak jak można byłoby się spodziewać (według podanych komentarzy w przykładzie), a dlaczego nie to zostawiam do przemyślenia ;)

Trzeba rozważyć wiele przypadków, mozliwości i problemów, o czym można się przekonać oddając się lekturze topicu Rzutowanie sprawdzające zakresy z pl.comp.lang.c.

Swoja drogą boost zawiera w swoich zbiorach numerycznych konwerterów własny, bezpieczny numeric_cast i chyba najrozsądniej, jeśli już trzeba to jego używać. Jego konstrukcja opiera się na podobnej do przedstawionej wyżej koncepcji.

Podobne notatki:

Może zainteresują Cię również następujące, pododbne notatki:

Nikt jeszcze nie skomentował tego wpisu.
Możesz być pierwszy.

Dodaj swój komentarz

Możesz użyć tych tagów XHTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Jeśli chcesz wstawić kilku linijkowy fragment kodu, użyj tagów <pre lang="x"></pre> (gdzie x język kodu np. cpp, perl, html). W ten sposób kod zostanie odpowiednio sformatowany i pokolorowany przez system.

Uwaga!

Na tym blogu działa system cache oraz filtr antyspamowy. Twój komentarz może być widoczny na stronie z pewnym opóźnieniem. Proszę o cierpliwość. Jeśli utraciłeś już wszystkie jej zasoby poinformuj mnie o tym, być może system uznał Cię za spamera ;)