
Andy Little wrote:
"Daniel Frey" <d.frey@gmx.de> wrote
Andy Little wrote:
"Tobias Schwinger" <tschwinger@neoscientists.org> wrote
Btw. Daniel Frey's library looks very interesting - did you take a look at it ?
I looked at it during the math constants review. I didnt look at the latest version, but I have now. Unfortunately it doesnt compile on VC7.1 but looks like a smarter version of my offering. (I guess that 's where the idea for mine came from.) OTOH it doesnt do eg double(pi) which syntax I happen to like.
Me too, but it doesn't work for generic types T. If T has several ctors that take different types (e.g. float, double, T), pi has no way to decide which cast would be appropriate.
I got around this ( I thought) in my quickie by using a traits class, but its messy... I guess.
You can't. Except you only offer a single conversion operator, but that means your solution doesn't scale anymore. It's a limitation from the language that cannot be worked-around. Or maybe we are talking about different things? I mean: struct SomeFloatType { SomeFloatType( double ); }; struct SomeConstant { template< typename T > operator T() const { return T(); } }; int main() { SomeConstant c; SomeFloatType x( c ); // ambiguous! } GCC 3.3.5 says: g++ -Wall -ansi -pedantic -O3 --message-length=0 t.cc -o t t.cc: In function `int main()': t.cc:14: error: call of overloaded `SomeFloatType(SomeConstant&)' is ambiguous t.cc:2: error: candidates are: SomeFloatType::SomeFloatType(const SomeFloatType&) t.cc:3: error: SomeFloatType::SomeFloatType(double) make: *** [t] Error 1 To sum it up: *Some* examples do work, but T(c) is not a *generic* syntax that works. Thus I went for .get<T>()
However IMO it shouldnt be convertible to anything. There needs to be some concept that it models. FWIW I would be content with , float, double long double. IOW numeric types. But ... eg FWIW my version still fails in boost::numeric::interval. This is always going to be the problem when trying to make one type maquerade as another :-(
FWIW, the constants I wrote only look as if they convert to anything. But in the end, you must have an implementation that yields the value. If there is no constant (or explicit mapper) for a type called "fluffy", the compiler complains. Static type checking should be preserved - and is. I tried to avoid magic that leads to surprises, as this immediatly leads to bugs in the real world.
It uses expression templates to allow "constant expressions" e.g: 'pi * two' or 'pow(two,one / twelve)'
Hm... I just had the idea of allowing a simple 'constant_<2> two;' to declare integer constants, but immediately ran into a more subtle problem involving two_value. Seems there's still something to redesign, so I have to play with this idea for some time...
A 'math constant' is expected to be pretty unexciting, which this doesnt deliver. Maybe if it was repackaged as say a quirky 'smart constant', rather than The std::math_constant it would be more gratefully received.
The constant itself is still simple: two. It should come from some header as well as all other constants you usually need. A normal user should not be concerned with defining constants. The best example is probably still: template< typename Y > inline typename SI< Y >::quantity idealGasLaw( const typename SI< Y >::pressure& p, const typename SI< Y >::volume& v, const typename SI< Y >::temperature& t ) { using boost::units::si::constants::chemistry::R; return p * v / ( R * t ); } The constant comes from a header, the user is not bothered with anything else at this point. Whatever float-point-type (native or UDT) he uses for Y, the algorithm as well as the constant library itself will be unaffected. You can define algorithm libraries containing the above, unit libraries, constant libraries (that is libraries that yield the constants for a certain use-case, not the library that helps to define these constants (my lib)) and float-point-types independently. A user might need to add some glue to use certain combinations in his projects, although most things for float/double will work out-of-the-box. The most important point is, that the user should never be forced to reinvent the wheel, only assemble some stuff! This is what I consider reuseability.
In an ideal world I guess one would be able to say e.g pow(my_num, n ,d ); and get the function template <typename T, int N, int D > T pow(T,N, D);
Here, I'm at a loss. Can you elaborate, please?
sure .. .... but of course it isnt doable in the language. (BTW the pi * pi stuff is cool !. Sorry... it appears I have been dismissive of that.)
int val = my::pow(9,3,2); eg replaces std::pow( static_cast<double>(9)
With my library, you can make pow(nine,three,two) a constant. Today. Given the ideas I have about constant_<9> nine; etc., this might even work for all integer numbers in the future, although I can't promise anything. If it works, you could also spell it sqrt(pow(nine,two)) or sqrt(nine*nine) - all leading to real constants :) Regards, Daniel