Boost logo

Boost Users :

Subject: Re: [Boost-users] What is the best way to obtain a constant one for any numeric type?
From: Arne Vogel (avogel_at_[hidden])
Date: 2014-05-19 12:45:36


On 19.05.2014 12:52, Javier Dehesa wrote:
> Is there any trait in Boost that allows me to get the value of one for
> any numeric type?
>
> What I'm looking for is something that would work like the following:
>
> boost::numeric_traits<int>::one; // 1
> boost::numeric_traits<long>::one; // 1L
> boost::numeric_traits<double>::one; // 1.0
> boost::numeric_traits<float>::one; // 1.0f
>
> And so on. Does it exist, or something equivalent? I've looked into
> NumericConversion, but I haven't quite found something similar. What I'm
> using now is something equivalent to the following:
>
> template<class Number>
> Number one()
> {
> return Number(1);
> }
>
> Maybe this is safe enough?
>
> I know I can do this trait by myself, but I would like to avoid it if
> possible, specially considering that I'm working on an already complex
> Boost library.
>
> Thanks.

Hello,

I doubt there's such a function in the public API of Boost.

However, your own solution has a greater potential than you might think,
because you can always add full specializations if needed.

Maybe your approach is to use a very broad definition of "one" as
multiplicative unity. Assuming you'd also use 4x4 matrices for 3D
coordinate transformation, then "one" would be the unit matrix (aka
identity matrix) in this context.

struct TransformMatrix
{
     double value[4][4];
};

// C++11: constexpr ...
const TransformMatrix unityMatrix{{1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0,
0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0}};

template<>
TransformMatrix one()
{
      return unityMatrix;
}

Note that the template argument is deduced - therefore "TransformMatrix
one()" is equivalent to "TransformMatrix one<TransformMatric">().

You cannot, however, partially specialize a function template and you
would have to use static methods in a template struct or class instead
if this is needed. It's possible to combine the two approaches so you
only have to specialize the struct/class when a partial specialization
is required:

template<typename T>
struct One
{
     static /*constexpr*/ T value()
     {
         return T(1);
     }
};

template<typename T>
T one()
{
     return One<T>::value();
}

// Full specialization
template<>
TransformMatrix one()
{
      return unityMatrix;
}

// Partial specialization
template<typename T>
struct One<std::complex<T> >
{
     static std::complex<T> value()
     {
         return std::complex<T>(one<T>(), 0);
     }
};

Of course, this particular specialization is usually superfluous and we
might want to define "zero" (additive unity) in an analogous way.

Regards,
Arne Vogel


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net