What is the best way to implement automatic type conversion between related types in C ++?

I implement 5 coordinate systems (let them be called A, B, C, D, E), each with its own unique type Coordinates<System>containing coordinates. I want the C ++ compiler to correctly transform between the coordinates of different systems. Coordinate transformations form a graph: ABCD and CE. Thus, we need to specify only 8 elementary transformations, and the compiler will generate the rest:

enum CoordSys { A,B,C,D,E };
template<CoordSys System> struct Coordinates;
template<> struct Coordinates<A> {  // specialisation for system A
   // ...
   operator Coordinates<B>() const; // implements transformation A -> B
};
template<> struct Coordinates<B> {  // specialisation for system B
   // ...
   operator Coordinates<A>() const; // implements transformation B -> A
   operator Coordinates<C>() const; // implements transformation B -> C
};
template<> struct Coordinates<C> {  // specialisation for system C
   // ...
   operator Coordinates<B>() const; // implements transformation C -> B
   operator Coordinates<D>() const; // implements transformation C -> D
   operator Coordinates<E>() const; // implements transformation C -> E
};
template<> struct Coordinates<D> {  // specialisation for system D
   // ...
   operator Coordinates<C>() const; // implements transformation D -> C
};
template<> struct Coordinates<E> {  // specialisation for system E
   // ...
   operator Coordinates<C>() const; // implements transformation E -> C
};

The compiler will perform the conversion between the coordinates of any two systems, for example

double radiusE(Coordinates<E> const&x); // radius is best computed from system E

template<CoordSys Sys> double radius(Coordinates<Sys> const&x)
{ return radiusE(x); }       // implicit type conversion to system E

, // ... ( , ). Coordinates<> - ? ?

+3
3

, .

, , , ( - ), :

 template<class X>
 class Coordinate {
     template <class Y>
     Coordinate(Coordinate<Y> that) { setFromCartesian(that.toCartesian()); }

     Coordinate<Cartesian> toCartesian() { ... }

     ....
 }

ctor , , .

enable_if , , :

   Coordinate<A> convert(Coordinate<B> that) { return ... }       

   template<class X, class Y>
   struct ConvertCheck {
        static const bool ok = False;
   };

   template<>
   struct ConvertCheck<A, B> {
        static const bool ok = True
   };

   ..

   template<class X>
   class Coordinate {  
         typedef Coordinate<X> this_type;

         template <class Y>
         Coordinate(Coordinate<Y> that, boost::enable_if(ConvertCheck<X,Y>::ok) { 
             *this = convert<this_type>(that);
         }

         ...
   }

, , ( boost:: mpl sometihng similiar). , , ...

+2

Coordinate, , (, A), ? -

class Coordinate {
public:
  CoordinateA toSystemA();
  CoordinateB toSystemB();
  // ..
};

, . , , ( , ).

+2

since you said that it is largely identical, my idea is this:

enum CoordSys { A,B,C,D,E };

template<CoordSys System>
struct Coordinates
{
    template<CoordSys XformSystem>
    operator Coordinates<typename
                         std::enable_if<!std::is_same<System, XformSystem>::value,
                                        XformSystem>::type
                        >() const
    {
        // implementation according to System -> XformSystem
    }
};

not verified thought, feel free to edit.

+1
source

All Articles