//promote_traits.h /** * The generic traits to promote numeric types in expressions, * just include this header to use it. * syntax: * typedef typename promote_traits::type result_type; * Copyright (C) 2003 olegabr&Co. All rights reserved. */ #ifndef OLEGABR_MEXP_PROMOTE_TRAITS_H #define OLEGABR_MEXP_PROMOTE_TRAITS_H #include #include "meta_tools.h" namespace mexp { /** * helper code for promote traits realization * hide it from the interface */ namespace detail { /** * generic if statament to choose the type * usage: * class A; * class B; * typedef typename IF<( i > 2 ), A, B>::result_type result_type; */ template struct IF { typedef thenType type; }; template struct IF { typedef elseType type; }; /** * mark the combination of types (built-in and complex) */ struct simple_simple_tag {}; struct complex_simple_tag {}; struct simple_complex_tag {}; struct complex_complex_tag {}; /* * for numeric_limits<> */ using namespace std; /** * helper to detect if T1 and/or T2 are built-in or complex types * type T is simple if numeric_limits::is_specialized is true */ template struct TAG { typedef typename IF< numeric_limits::is_specialized && numeric_limits::is_specialized, simple_simple_tag, typename IF< numeric_limits::is_specialized && !numeric_limits::is_specialized, simple_complex_tag, typename IF< !numeric_limits::is_specialized && numeric_limits::is_specialized, complex_simple_tag, complex_complex_tag >::type >::type >::type tag_type; }; //struct TAG<> } //namespace detail /** * the promote traits for scalar types * T1, T2 can be either built-in scalar types or * complex user defined types. * in this case it MUST define value_type in its interface * * if one is integer and other not, get other * if types are built-in get one with greater number of digits in mantissa * else if one of them is complex and another is built-in get the complex * else if both of them are complex repeat all of this recursively for the T::value_type * of each complex type and choose the "T" with more accurate "value_type" */ template ::tag_type> struct promote_traits; template struct promote_traits { typedef typename detail::IF< (std::numeric_limits::is_integer && !std::numeric_limits::is_integer), T2, typename detail::IF< (!std::numeric_limits::is_integer && std::numeric_limits::is_integer), T1, typename detail::IF< /* both integer or both float */ (std::numeric_limits::digits10 > std::numeric_limits::digits10), T1, T2 >::type >::type >::type type; }; //struct promote_traits<> template struct promote_traits { typedef T1 type; }; template struct promote_traits { typedef T2 type; }; template struct promote_traits { typedef typename detail::IF< util::types_equal< typename promote_traits< typename T1::value_type, typename T2::value_type >::type, typename T1::value_type >::res, T1, T2 >::type type; }; //struct promote_traits<> } // namespace mexp #endif //OLEGABR_MEXP_PROMOTE_TRAITS_H