簡體   English   中英

模板的編譯時類型名別名

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM