使用模板元编程提供强大的坐标系
Using template metaprogramming to provide strongly-typed coordinate systems
我正在尝试定义一个3D'坐标'类,该类在'CoordinateSystem'参数上进行了强烈构成。我正在使用的当前机制的简化版本:
class CoordinateBase {
protected:
double a, b, c;
/* millions of constructors */
}
class System1 : protected CoordinateBase {
public:
double& X() {return a;}
double& Y() {return b;}
double& Z() {return c;}
protected:
/* millions of constructors */
}
class System2 : protected CoordinateBase {
public:
double& Lat() {return a;}
double& Lon() {return b;}
double& Alt() {return c;}
protected:
/* millions of constructors */
}
template<typename T>
class Coordinate : public T {
public:
/* millions of constructors */
}
这有效,但是我对树中每个级别所涉及的样板量不满意(无argument/explicit values/copy/move构造函数,分配运算符)。我想保留具有不同系统的坐标轴的不同名称的能力。
使用诸如CRTP之类的东西似乎很有帮助;然后,我可以让存储在坐标类中的实际坐标值的成员并使用静态多态性从System1和System2中获取它们。不幸的是,我不能这样做:
template<typename T>
class Coordinate : public T<Coordinate<T>>
或至少不允许编译器,可能是因为我缺少一些语法。
我考虑的另一种可能性是将所有启用/禁用逻辑放在坐标中:
template<typename T>
class Coordinate {
public:
std::enable_if<std::is_same<T, System1>::value, double&> X() {return a;}
private:
double a;
}
,但这将变得相当丑陋,并放置了所有不愉快的模板机械,此类无辜的用户将看到它。
我不确定这种方法是哪种最佳方法。我如何避免在保持我想要的接口时定义这么多样板构造函数/分配运算符?
template<typename T>
class Coordinate : public T<Coordinate<T>>
上面的代码无效C ,因为T
是一种类型,但是您使用的IS好像是template
。这也不是CRTP-这是适当CRTP的示例:
template <typename T>
struct base
{
auto& as_derived() { return static_cast<T&>(*this); }
const auto& as_derived() const { return static_cast<const T&>(*this); }
};
struct derived : base<derived>
{
// ...
};
您可以尝试以这种方式使用CTRP:
template <typename T>
struct base
{
auto& as_derived() { return static_cast<T&>(*this); }
const auto& as_derived() const { return static_cast<const T&>(*this); }
double _x, _y, _z;
base(double x, double y, double z) : _x{x}, _y{y}, _z{z} { }
base(double v) : _x{v}, _y{v}, _z{v} { }
};
struct coord : private base<coord>
{
public:
using base<coord>::base;
auto& x() { return this->_x; }
auto& y() { return this->_y; }
auto& z() { return this->_z; }
};
struct geocoord : private base<geocoord>
{
public:
using base<geocoord>::base;
auto& lat() { return this->_x; }
auto& lon() { return this->_y; }
auto& alt() { return this->_z; }
};
int main()
{
coord c0{1,2,3};
geocoord c1{1};
c0.x() = 10;
c1.alt() = 22;
}
wandbox上的实时示例
最终解决了这样的问题:
template<typename T>
class CoordinateBase {
protected:
Coordinate<T>* upcast() {return static_cast<Coordinate<T>*>(this);}
const Coordinate<T>* upcast() const {return static_cast<const Coordinate<T>*>(this);}
};
class System1 : private CoordinateBase<System1> {
double& X() {return upcast()->c1;}
// other coordinates etc.
};
template<typename T>
class Coordinate : public T {
public:
/* Constructors */
private:
double c1;
double c2;
double c3;
friend class System1;
};
typedef Coordinate<System1> System1Coordinate;
sota-crtp,但我依靠约定来使static_cast&lt;>安全而不是模板参数和约定。我已经阐述了一些名称空间和事物,这意味着坐标和system1并不是很暴露于公众。
这种方法的优点:
- 坐标系统类只有坐标系统专门允许(主要获得坐标)的操作
- 所有的构造函数都生活在顶层,因此无需定义或
using
在下部下方 - 在层次结构的顶部有一个类,我可以为所有坐标(或一些重要的子集)定义事物,例如算术操作
- 相对安全。我可以static_assert,坐标已通过坐标键的某些东西,我可以将所有系统保留在自己的名称空间中,以"内部"之类的名称,因此不鼓励人们使用它们,可以使坐标系统抽象使他们可以抽象't自己实例化,如果您忘记添加"朋友"声明,它不会编译,并且只能通过适当的坐标名称访问坐标。
- 易于理解。
缺点:
- 没有真正的方法来确保坐标库中的static_cast是安全的。
- 朋友声明
相关文章:
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 模板元编程:如何将参数包组合成新的参数包
- Qt Q串行端口未编程设备未关闭
- 模板元编程 - 尝试实现维度分析
- 我是编程新手
- C++编程从外部文本文件定义数组大小
- 了解算法的性能差异(如果以不同的编程语言实现)
- 使用 Gtkmm 以编程方式选择 Gtk::TextView 中的文本
- 如何将可变参数模板转换为多个单个模板?(C++竞争编程调试模板)
- OpenGL 着色器坐标系
- 使用命名空间正确编程
- C++编程:运算符重载中的引用如何工作?
- Arduino 模块化编程与全局和设置
- C++ 运算符修改/元编程策略,用于不那么冗长的语法
- 在没有管理员权限的情况下,在 c++ 中以编程方式将程序添加到启动
- 如何以编程方式将音频从任何录制设备路由到任何播放设备
- 试图修复一个错误,该错误不会让我开始编程其余部分
- C++模板编程设计问题 - 根据输入文件返回不同的类型
- 使用模板元编程提供强大的坐标系