2011-08-28 39 views
1

編輯:我發現並編寫了一個解決方案,但我沒有回答這個問題,因爲我的解決方案可能仍然不理想。從任意地圖獲取指向mapped_type的指針或引用

我正在寫一個小型庫,用於在地圖上執行例程,但我在設計一組類模板時會遇到麻煩,這些模板會讓我得到一個指針或引用(取決於地圖的value_type的second_type )映射到mapped_type,而不管映射的類型(例如std :: map,boost :: ptr_map)。

爲了進一步闡述,我列出了一些輸入類型和所需的輸出類型。

Case Input Type         Output Type 
A  std::map<int, std::map<int, int> >   std::map<int, int>& 
B  std::map<int, boost::ptr_map<int, int> >  boost::ptr_map<int, int>& 
C  boost::ptr_map<int, std::map<int, int> >  std::map<int, int>* const 
D  std::map<int, std::map<int, int> >*   std::map<int, int>& 
E  std::map<int, boost::ptr_map<int, int> >* boost::ptr_map<int, int>& 
F  boost::ptr_map<int, std::map<int, int> >* std::map<int, int>* const 

我的代碼經過的情況下A,B,d和E,但未能對案件C和F這裏是我到目前爲止所。

template <class Map> 
struct map_utils 
{ 
    template <class K> 
    static typename 
    boost::remove_pointer< 
      typename Map::value_type 
    >::type::second_type& 
    get(Map& m, const K k) 
    { 
      return m[k]; 
    } 

    template <class K> 
    static typename 
    boost::remove_pointer< 
      typename Map::value_type 
    >::type::second_type& 
    get(const Map& m, const K k) 
    { 
      return const_cast<Map&>(m)[k]; 
    } 
}; 

template <class Map> 
struct map_utils<Map*> 
{ 
    template <class T> 
    static typename 
    boost::remove_pointer< 
      typename Map::value_type 
    >::type::second_type& 
    get(Map* m, const T t) 
    { 
      return (*m)[t]; 
    } 

    template <class T> 
    static typename 
    boost::remove_pointer< 
      typename Map::value_type 
    >::type::second_type& 
    get(const Map* m, const T t) 
    { 
      return const_cast<Map*>(m)->operator[](t); 
    } 
}; 

我想使用boost :: MPL要做到這一點,這是我到目前爲止已經熟了起來,但我得到使用的代碼的兩個版本相同的錯誤。

錯誤。

error: invalid initialization of reference of type ‘std::map<int, double>* const&’ from   expression of type  ‘boost::ptr_container_detail::reversible_ptr_container<boost::ptr_container_detail::map_config<std::map<int, double>, std::map<int, void*, std::less<int>, std::allocator<std::pair<const int, void*> > >, true>, boost::heap_clone_allocator>::Ty_’ 

修改後的結構專用於處理不是指向映射的指針的l值。

template <class K> 
static typename boost::remove_pointer< 
     typename Map::mapped_type 
>::type& 
get(Map& m, const K k) 
{ 
     return m[k]; 
} 

只需要方法的身體在改變:

template <class K> 
    static typename 
    boost::mpl::if_< 
      boost::is_pointer< 
        typename boost::remove_pointer< 
          typename Map::value_type 
        >::type::second_type 
      >, 
      typename boost::remove_pointer< 
        typename boost::remove_const< 
          typename Map::value_type 
        >::type 
      >::type::second_type, 
      typename boost::remove_pointer< 
        typename Map::value_type 
      >::type::second_type& 
    >::type 
    get(Map& m, const K k) 
    { 
      return m[k]; 
    } 

回答

1

C和F似乎不對,映射類型不是boost :: ptr_map。否則,它聽起來像你可以使用完整的模板特化來決定它是一個std :: map或boost :: ptr_map。類似這樣的:

template <class Map> 
class Whatever; 

template <class K, class V> 
class Whatever<std::map<K, V> > 
{ 
    public: 
     typedef V& Type; 
}; 

template <class K, class V> 
class Whatever<std::map<K, V>* > 
{ 
    public: 
     typedef V& Type; 
}; 

template <class K, class V> 
class Whatever<boost::ptr_map<K, V> > 
{ 
    public: 
     typedef V* const Type; 
}; 

template <class K, class V> 
class Whatever<boost::ptr_map<K, V>* > 
{ 
    public: 
     typedef V* const Type; 
}; 
+0

糟糕,我的壞 - 現在已經修好了。 –

+0

您的解決方案比我的優雅得多 - 我沒有想過使用模板參數來表示鍵和值類型。 –

+0

爲了適應任意的地圖類型,你可以在'class Whatever'的非特化版本中將'class Map'更改爲'template Map'。 –

0

我,通過使用mapped_type的typedef像這樣得到的代碼編譯成功,並大大簡化了它在這個過程中以上問題中定義的結構的專門版本,以便適應指向地圖的指針。如果你想要整個代碼清單,讓我知道,我會在這裏轉儲整個事情。