jeudi 28 juillet 2016

How to test if exists a template function specialization

I'm managing units conversion. Say us that I reached a state where I achieve that.

The heart of my conversion between different units lies on the following generic template function:

template <class SrcUnit, class TgtUnit> extern
double convert(double val);

The goal of this function is to convert a physical magnitude expressed in units of type SrcUnit to another expressed in units of type TgtUnit.

I have a class called Quantity<Unit> which manages the values and their unities and this class tries to give type safety and automatic conversion. By example, I export the following constructor:

  template <class SrcUnit>
  Quantity(const Quantity<SrcUnit> & q)
    : unit(UnitName::get_instance())
  {
    check_physical_units(q); // verify that the physical magnitudes are the same
    value = convert<SrcUnit, UnitName>(q.value); // <<- here the conversion is done
    check_value(); // check if the value is between the allowed interval
  }

I export other stuff where the conversion is done.

So, when someone wishes to manage a new unit, she specifies a new Unit derived class. I achieve that by putting inside a macro all the needed specification of the new class. Now, it is the responsibility of this user to write the conversions functions. That is to write two specializations of the convert() template. By example, suppose that you have a unit called 'Kilometerand you wish to specify a new unit calledMile`. In this case, you do this:

Declare_Unit(Mile, "mi", "English unit of length", Distance,
         0, numeric_limits<double>::max()); // macro instantiating a new Unit class
template <> double convert<Kilometer, Mile>(double val) { return val/1609.344; }
template <> double convert<Mile, Kilometer>(double val) { return 1609.344*val; }

Now, what happen if the user forgets to write a conversion function? Well, in this case the linker will fail because it cannot find the convert() specialization.

Now my question.

Although I think a linker error is acceptable as behavior for reporting to the user the missing convert(), I would like to test i compiling time for the existence of convert() specialization. So my question is how could I achieve that? I guess through a static_assert put just before each call to convert() which tests if the specialization is already known. But how to do that?

PS: Also, it would be very useful for me if someone could recommend me a good text about C++ metaprogramming.

Aucun commentaire:

Enregistrer un commentaire