3

Coordinates<System>私は5つの座標系(A、B、C、D、Eと呼びましょう)を実装しており、それぞれが座標を保持する独自のタイプを持っています。異なるシステムの座標間でC++コンパイラが自動的に正しく変換されるようにしたい。座標変換はグラフを形成します:ABCDとCE。したがって、8つの基本変換のみを指定する必要があり、コンパイラーが残りを生成します。

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
};

コンパイラは、たとえば、任意の2つのシステムの座標間の変換を実行します。

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

ただし、// ...パーツが長く、ほとんど同じである可能性があるため、特殊化は面倒です(共通ベースから継承する場合は、それでも面倒です)。理想的には、特殊化を避け、クラステンプレートの定義を1つだけにしたいのですが、Coordinates<>どうすればよいでしょうか。または、別の便利なオプションはありますか?

4

3 に答える 3

2

Coordinateすべてのシステムに変換可能な内部表現を持ち(たとえば、データをシステムに格納するA)、特殊な型に変換するためのいくつかのメソッドがある単純な型を選びませんか?何かのようなもの

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

そもそもなぜここにテンプレートが必要なのかさえわかりません。変換を連鎖させる代わりに、特殊化に変換できる標準表現を使用するという考え方です(関数のシグネチャがよりわかりやすくなるように、座標系ごとに特殊なタイプを使用することを想定しています)。

于 2012-04-18T10:11:15.177 に答える
2

convert-toメンバー関数としてではなく、コンストラクターで暗黙的な変換を行います。

そうすれば、座標タイプに対してテンプレートコンストラクターを使用できます。変換の全速力が必要ない場合は、すべてをデカルト(またはその他)に変換してから、特別な表現に変換できます。

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

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

     ....
 }

次に、専用コードの速度を必要とする変換にそのctorを特化できますが、他のほとんどのコードには上記のバージョンを残します。

enable_if関数とfree関数を使用して、コンストラクターが正しく失敗することを確認することもできます。

   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);
         }

         ...
   }

もう1つの方法は、メタプログラミングを使用して変換チェーンを定義し、正しいシーケンスを呼び出すことです(boost :: mplまたはsometihngsimiliarを使用)。それは素晴らしい運動になるでしょう、それは私が今肉付けする時間がありません...

于 2012-04-18T10:54:59.803 に答える
1

ほぼ同じだとおっしゃっていたので、私の考えは次のようになります。

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
    }
};

テストされていない考えです。自由に編集してください。

于 2012-04-18T10:40:52.480 に答える