[英]Compile-time typename aliasing for templates
在我的碰撞/物理引擎中,由於有了模板,我知道運行時正在使用哪種空間分區方法。 我正在嘗試創建一個通用的Query
類,該類允許我對任何空間分區方法執行相同的查詢。 每種空間分區方法都實現其自己的查詢版本,但是接口是相同的。
問題在於,用戶必須指定空間分區類型 , 空間分區類型的查詢類型以及空間分區類型的查詢模式 。
如果用戶要更改其空間分區方法,則所有現有代碼都會中斷。
有沒有一種方法允許用戶僅指定空間分區類型 ,通用查詢類型和通用查詢模式,並具有某種別名,以便自動選擇正確的類型(相對於空間分區類型)?
我已經嘗試過using
(C ++ 11 typedef
)和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!
實際代碼還會傳遞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;
}
接下來,在每個空間分區實現中,我們都專門化類型和模式。 例如,在Quadtree.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();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.