Boost logo

Boost :

From: Daniel Frey (d.frey_at_[hidden])
Date: 2005-05-10 15:05:03


Andy Little wrote:
>
> "Daniel Frey" <d.frey_at_[hidden]> wrote
>
>> Andy Little wrote:
>>
>>>
>>> "Tobias Schwinger" <tschwinger_at_[hidden]> 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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk