抱歉标题,我找不到更合适的名字。如果有人有更好的,我很乐意改变它。
假设我们有一组实体几何对象:
struct ray { ... };
struct plane { ... };
struct box { .... };
struct sphere { .... };
我目前正在考虑交叉算法的模板函数,以便我们可以根据运行时检查的类型创建函数的专用版本:
template <typename operand_type1,
typename operand_type2>
RET_DATA check_intersection(operand_type1 operand1, operand_type2 operand2){ ... };
对于 ray/shpehre 相交,我们将提供以下实现:
template<> RET_DATA check_intersection<ray, sphere>(ray operand1, sphere operand2){ ... };
我故意未定义 RET_DATA,因为根据每个专业化,我们可能希望返回不同的信息。例如对于这种情况,我们可以返回交叉点的数量(如果有的话)和相关的点。对于球体-球体,我们可以返回相交的体积。问题是我们还需要创建这个模板的用户需要知道的新(返回)类型。
我目前最好的候选想法是创建一个仿函数并专门针对每种类型。在仿函数内部定义一个返回结构,每个特化都有一个通用名称(即result):
/** templated functor */
template<typename T1, typename T2> struct check_intersect {
typedef intersection_data<T1, T2> result;
check_intersect(T1 operand1, T2 operand2) : operand1(operand1), operand2(operand2) {}
result operator()(T1 operand1, T2 operand2){ ... }
};
/** tempalted auxiliar return data type */
template<typename T1, typename T2> struct intersection_data { ... }
然后,我们将根据数据类型为两者提供专业化。这或多或少地以这种使用模式结束:
check_intersect<ray, sphere>::result ret = check_intersect<ray, sphere>(my_ray, my_sphere);
尽管使用现代 IDE,问题以某种方式减少了,但用户仍然必须猜测界面的结果。这是我不喜欢的地方。
这种方法有缺陷吗?有没有更好的设计理念来解决即将推出的实体几何类型的可扩展性?这是最优雅的方法吗?
也许模板不是正确的工具,我可以为每种情况提供不同的功能......
谢谢你。