模板的编译时类型名称别名
Compile-time typename aliasing for templates
在我的碰撞/物理引擎中,多亏了模板,我知道我在运行时使用的是什么空间分区方法。我正在尝试创建一个通用的Query
类,它允许我对任何空间分区方法执行相同的查询。每个空间分区方法都实现自己版本的查询,但接口是相同的。
问题是,用户必须指定空间分区类型、空间分区类型的查询类型以及空间分区类型的询问模式。
如果用户要更改其空间分区方法,那么所有现有的代码都将中断。
是否有一种方法允许用户只指定空间分区类型、通用查询类型和通用查询模式,并具有某种别名,以便自动选择正确的类型(相对于空间分区类型)?
我尝试过using
(C++11typedef
)和decltype
以及部分专业化,但我找不到正确的代码编写方法,也从未编译/工作过。
我只能考虑使用virtual
方法和基类,但这似乎没有必要,因为我在编译时"知道"这些类型。
当前代码:
// Query.h
template<class T, class U, class V>
Query<T, U, V> getQuery() { return Query<T, U, V>(getSpatial<T>()); }
// Example.cpp (user project)
getQuery<Grid, GridQueryType::Point, GridQueryMode::All>();
getQuery<QuadTree, QuadTreeQueryType::Point, QuadTreeQueryMode::All>();
所需代码(无效):
// Query.h
namespace Type { struct Point; }
namespace Mode { struct All; }
template<class T, class U, class V>
Query<T, typename T::U, typename T::V> getQuery()
{
return Query<T, typename T::U, typename T::V>(getSpatial<T>());
}
// Grid.h
using Type::Point = GridQueryType::Point;
using Mode::All = GridQueryMode::All;
// QuadTree.h
using Type::Point = QuadTreeQueryType::Point;
using Mode::All = QuadTreeQueryMode::All;
// Example.cpp (user project)
getQuery<Grid, Type::Point, Mode::All>(); // actually uses GridQueryType::Point and GridQueryMode::All!
getQuery<QuadTree, Type::Point, Mode::All>(); // actually uses QuadTreeQueryType::Point and QuadTreeQueryMode::All!
Real代码还传递typename... TArgs
以允许查询类型特定的参数——出于空间原因,我将其从示例中排除。
如果第一个模板参数与第二个和第三个模板参数之间存在直接关系,则后一个参数似乎不应被视为模板参数,而是由类型映射确定:
template <typename> struct TypePoint;
template <typename> struct ModeAll
template <> struct TypePoint<Grid> { typedef GridQueryType::Point type; };
template <> struct ModeAll<Grid> { typedef GridQueryMode::All type; };
getQuery<Grid>();
至少,使用如上所述的类型映射,您可以为参数定义默认值。如果后面要添加其他参数,基本上可以将前三个参数及其默认值分组为一个类型,然后传递,例如:
template <typename T,
typename P = typename TypePoint<T>::type,
typename M = typename ModeAll<T>::type>
struct QueryParameters {
typedef T type;
typedef P point_type;
typedef M mode_type;
};
getQuery<QueryParemeters<Grid>, Other, Paremters>();
我认为这里的解决方案是模板专业化和模板模板参数的组合。
首先,我们定义了不同类型的查询:
namespace Type
{
template<typename SPATIAL_PARTITION>
struct Point;
}
namespace Mode
{
template<typename SPATIAL_PARTITION>
struct All;
}
接下来,在每个空间划分实现中,我们专门化类型和模式。例如,在四叉树.h:中
namespace Type
{
template<>
struct Point<Quadtree>
{
/* ... implementation here ... */
}
}
namespace Mode
{
template<>
struct All<Quadtree>
{
/* ... implementation here ... */
}
}
最后,在查询中,我们使用模板模板参数来指定模式和类型:
template<typename SPATIAL_PARTITION, template<typename> class TYPE , template<typename> class MODE>
void getQuery()
{
using type = TYPE<SPATIAL_PARTITION>;
using mode = MODE<SPATIAL_PARTITION>;
}
我会转向另一个方向。由于你有模板函数,你可以使用类型推导。返回对象取决于函数模板参数。因此,您可以用typedef返回类型来代替别名。
// Grid.h
//using Type::Point = GridQueryType::Point;
// using Mode::All = GridQueryMode::All;
typedef Query<Grid, GridQueryType::Point, GridQueryMode::All> T_one;
// QuadTree.h
//using Type::Point = QuadTreeQueryType::Point;
//using Mode::All = QuadTreeQueryMode::All;
typedef Query<Grid, QuadTreeQueryType::Point, QuadTreeQueryMode::All> T_two;
// Example.cpp (user project)
//getQuery<Grid, Type::Point, Mode::All>(); // actually uses GridQueryType::Point and
//getQuery<QuadTree, Type::Point, Mode::All>();
T_one t = getQuery();
T_two t2 = getQuery();
- 继承模板类中的类型别名
- 为什么 GCC 在使用类型别名时处理 const reinterpret_cast不同?
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- C++模板/别名 - 模板参数列表中参数 1 处的类型/值不匹配
- 如何使用类型别名从模板化类中隐藏模板列表
- 如何检测类型类型别名?
- C++类型别名,其中值被替换
- 在Qt中注册自定义元类型的别名类型
- 使用外部定义的模板类型作为模板参数的更通用模板的模板别名
- 如何为流输出运算符提供重载<<模板'using'类型别名?
- 通过类型别名从构造函数转发模板推导
- C++通过别名指针以静默方式将错误的类型分配给数组元素
- 为什么此模板定义了一组匹配void的别名类型
- 如何返回类中别名类型的值
- 在不键入别名类型的完整声明的情况下,无法从类模板定义中访问类型的类型别名
- 依赖于参数的查找在来自另一个命名空间的别名类型上意外行为
- 为什么我不能用"unsigned"限定别名类型?
- 当涉及到友谊时,为什么别名模板会与别名类型模板区别对待
- size_t是否保证是整数类型之一的别名类型?
- 将别名模板强制转换为别名类型