On Thu, 19 Jun 2003 19:51:31 +0100, "Paul A Bristow" <[EMAIL PROTECTED]> wrote:
>| Well, you wanted to know what is likely to be accepted. In a >| formal review (this isn't anymore, AFAIU, is it?) I would >| vote no to your approach. > >But would you vote yes if the only presentation was Daniel's method? Overall? What I like in his code is the use of template specialization to provide the values for different types, and the possibility to add UDTs. OTOH, I'm not sure whether the conversion function template and the pre-built binary operators (see ADD_OPERATOR) are worth having. Personally I won't probably use those operators, as they are just syntactic sugar to avoid an explicit cast of the constant instance to the type of its (left or right) "neighbour". Of course that's different from what we are used to with built-in constant variables (floating point promotion). Example: if I have const double pi = ...; then in pi * f * d the language assures me that f is promoted to a double as well and the result is a double. When I use "class pi" instead the selected type of the constant (through pi_value) becomes the one of the adjacent operand, which is quite a different thing. So you have a familiar appearance (you write the expression as if 'pi' had a built-in type, with the usual operators etc.) with an unfamiliar behavior. I'm not saying that is necessarily wrong but, not having any concrete experience with it, I'm not sure it is a good thing either. However, one can explicitly static_cast, so those who want to be "safe" can be. Of course, if you leave there the conversion function but not the operators you end up with the same behavior in most cases, thanks to the built-in candidates in overload resolution. And a conversion function can't be made 'explicit' (for now?). A possibility could be to use some "floating point promotion" traits (one trivial implementation is in the Yahoo files section), to select the *promoted* neighbour type, but that's probably not worth the trouble. Summarizing: I think Daniel is on the right track, but I'm not particularly fond of the automatic "conversions" (actually they are automatic "selections" of the type, based on the context of usage - and since the selection mechanism is different from the built-in one...) >I am only really concerned that the accurate constants become more >standardised, in name and value. Yes. Just to stimulate discussion, and without any offence towards Daniel's solution, this is an approach without the conversion function and the operator overloads. Beware that it's completely untested. namespace math { // Generic base class for all constants template< typename T /*, template< class > class F*/ > struct constant {}; // value_type selector basically says what's the // template class (pi_value, gamma_value, etc.) whose // specializations give the different values. It avoids // using template template parameters, which aren't // supported by all compilers. template<typename T> struct value_selector; template <typename U, typename T> U as(const constant<T> & c) { value_selector<T>::type<U>::spec obj; return obj(); }; // Here's the definition for pi for some // usual types (can be extended by UDTs) // template<typename T> struct pi_value; template<> struct pi_value<float> { float operator()() { return 3.14f; } }; template<> struct pi_value<double> { double operator()() { return 3.1415; } }; template<> struct pi_value<long double> { long double operator()() { return 3.141592L; } }; // Here's the single line to create a useful interface struct pi_type : constant< pi_type > {} pi; // Here's the line to tell that the value of type T // for the constant pi is given by pi_value<T> template <> struct value_selector<pi_type> { template <typename U> struct type { typedef pi_value<U> spec; }; }; //--------------------------------- // another constant (pi ** 2) template< typename T > struct pi2_value; template<> struct pi2_value<float> { float operator()() const { return 9.87f; } }; template<> struct pi2_value<double> { double operator()() const { return 9.8696; } }; template<> struct pi2_value<long double> { long double operator()() const { return 9.8696044L; } }; struct pi2_type : constant<pi2_type> {} pi2; template <> struct value_selector<pi2_type> { template <typename U> struct type { typedef pi2_value<U> spec; }; }; //--------------------------------------- // Some obvious (?) constants: // #define CONSTANT_VALUE( name, value ) \ template< typename T > struct name##_value \ { T operator()() const { return value; } }; \ \ struct name##_type : constant<name##_type> {} name; \ \ template<> \ struct value_selector<name##_type> { \ template <typename U> struct type { \ typedef name##_value<U> spec; \ }; \ }; /**/ CONSTANT_VALUE( minus_one, -1 ); CONSTANT_VALUE( zero, 0 ); CONSTANT_VALUE( one, 1 ); CONSTANT_VALUE( two, 2 ); CONSTANT_VALUE( three, 3 ); CONSTANT_VALUE( ten, 10 ); #undef CONSTANT_VALUE // And their relationship: pi2_type operator*( const pi_type&, const pi_type& ) { return pi2_type(); } } #include <cmath> namespace std { //--------------------------------------- // example: exact value of a function math::pi_type acos(math::minus_one_type /* no parameter name */ ) { return math::pi_type(); } }; #include <iostream> #include <ostream> using namespace std; int main() { // Usage example: using math::pi; using math::pi2; using math::two; cout.precision(10); cout << math::as<double>(pi) << '\n'; const float f = 1.0f; //pi * f; // doesn't work cout << math::as<double>(pi) * f << '\n'; cout << math::as<long double>(pi * pi) << '\n'; cout << math::as<long double>(pi2) << '\n'; cout << math::as<long double>(std::acos(math::minus_one)) << '\n'; } > >Paul > >PS I'd like to hear more views on this - >previous review comments were quite different, >being very cautious about an 'advanced' scheme like this. It's not so "advanced" as it might appear at first sight. Maybe the rigmarole above, together with the comments in the alternative solution, is of some help to realize that the basic ideas are very simple. Genny. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost