Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么';在C+中,实现相关类型之间自动类型转换的最佳方法是什么+;?_C++ - Fatal编程技术网

C++ 什么';在C+中,实现相关类型之间自动类型转换的最佳方法是什么+;?

C++ 什么';在C+中,实现相关类型之间自动类型转换的最佳方法是什么+;?,c++,C++,我正在实现5个坐标系(我们称它们为A、B、C、D、E),每个坐标系都有自己独特的类型坐标保存坐标。我希望C++编译器在不同系统的坐标之间自动转换。坐标变换形成一个图形:a-B-C-D和C-E。因此,我们只需要指定8个初等变换,编译器将生成其余的: enum CoordSys { A,B,C,D,E }; template<CoordSys System> struct Coordinates; template<> struct Coordinates<A>

我正在实现5个坐标系(我们称它们为A、B、C、D、E),每个坐标系都有自己独特的类型
坐标
保存坐标。我希望C++编译器在不同系统的坐标之间自动转换。坐标变换形成一个图形:a-B-C-D和C-E。因此,我们只需要指定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
};
enumcoordsys{A,B,C,D,E};
模板结构坐标;
模板结构坐标{//系统A的专业化
// ...
运算符坐标()const;//实现转换A->B
};
模板结构坐标{//系统B的专业化
// ...
运算符坐标()const;//实现转换B->A
运算符坐标()const;//实现转换B->C
};
模板结构坐标{//系统C的专业化
// ...
运算符坐标()const;//实现转换C->B
运算符坐标()const;//实现转换C->D
运算符坐标()const;//实现转换C->E
};
模板结构坐标{//系统D的专业化
// ...
运算符坐标()const;//实现转换D->C
};
模板结构坐标{//系统E的专业化
// ...
运算符坐标()const;//实现转换E->C
};
例如,编译器将完成任意两个系统坐标之间的转换

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
双半径(坐标常数&x);//半径最好由系统E计算得出
模板双半径(坐标常量和x)
{返回半径(x);}//到系统E的隐式类型转换

然而,专业化是乏味的,因为
/…
部分可能很长,并且基本相同(如果我从一个公共基础继承,这仍然是乏味的)。理想情况下,我希望避免专业化,只定义一个类模板
坐标
——我该怎么做?或者还有其他有用的选项吗?

您可以选择一个简单的
坐标类型,它有一些可转换为所有系统的内部表示(例如,它将其数据存储在系统
a
中),然后使用一些方法转换为专用类型?差不多

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

我甚至不知道你为什么首先需要模板。其思想是,不使用链式转换,而是使用一种可以转换为专门化的规范表示法(假设您希望在每个坐标系中使用专门化类型,以便您的函数签名更具描述性)。

由于您说它基本相同,我的想法如下:

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
    }
};
enumcoordsys{A,B,C,D,E};
模板
结构坐标
{
模板
运算符坐标::类型
>()常数
{
//根据系统->XformSystem执行
}
};

未经测试的想法,请随意编辑。

我将在构造函数中进行隐式转换,而不是转换为成员函数

这样,您可以在坐标类型上使用模板构造函数,如果不需要全速转换,您可以将所有内容转换为笛卡尔(或任何形式),然后转换为特殊表示:

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

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

     ....
 }
模板
类坐标{
模板
坐标{setFromCartesian(that.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);
         }

         ...
   }
坐标转换(坐标){return…}
模板
结构转换检查{
静态常数布尔ok=假;
};
模板
结构转换检查{
静态常数布尔ok=真
};
..
模板
类坐标{
typedef协调此_类型;
模板
协调(协调,boost::enable_if(ConvertCheck::ok){
*这个=转换(那个);
}
...
}

另一种方法是使用元编程定义转换链并调用正确的序列(使用boost::mpl或类似的方法)。这将是一个很好的练习,我现在没有时间充实它…

最好避免隐式转换,而不是创建更多的转换。如果您需要为每个系统专门化,那么您不应该在这里使用模板。我认为这不可行。编译器只查找一个用户定义的转换,而不是序列执行隐式转换时的转换次数。在您的示例中,编译器必须执行两次用户定义的转换才能将
坐标
转换为
坐标
@Xeo我不需要对每个系统进行专门化,只需要对转换进行专门化。“我们只需要指定8个基本转换,编译器将生成其余的转换”-这不是真的,因为转换链只能包含一个用户定义的转换。这是一种不同的设计模式,更简单,但是(取决于应用程序)这是我最初的设计,除了
enable_if
之类的东西。我想我可以避免显式地给出所有20个可能的转换操作,但这似乎不可能……想法:编写一个简单的程序来生成不同的代码(或转换参数)用于不同的坐标系。您只需要编写其中的8个,然后生成剩余的。最后使用您的专门化方法或enable_if方法。希望这有帮助。我喜欢这样