2017-04-01 43 views
1

我有traits類,說:模板特性病的所有迭代器::地圖

template <class T> 
struct KeyValueTraits 
{ 
    typedef typename T::key_t key_t; 
    typedef typename T::value_t value_t; 
} 

現在我想聲明這個特性的專業化的std::map

template < typename... Args > 
struct KeyValueTraits<typename std::map<Args...>::iterator > 
{ 
    typedef std::map<Args...> target_t; 
    typedef typename target_t::key_type key_t; 
    typedef typename target_t::mapped_type value_t; 
}; 

編譯器的所有迭代器引發錯誤:

error C2764: 'Args': template parameter not used or deducible in partial specialization

那麼如何聲明所有可能的特徵類型std::map<...>::iterator

+1

你不能。不是你無論如何都試圖去做的方式。沒有辦法從迭代器中提取容器類型。您可以嘗試使用'first'和'second'(需要C++ 11)。 –

+0

您試圖解決什麼問題?有一些解決方案適用於任何具有'std :: pair 的迭代器作爲值類型。一旦你有迭代錯誤,並不總是有可能獲得有關容器的信息。 –

回答

1

這裏有一個可能的解決方案(它改變了KeyValueTraits模板簽名,因爲它看起來不可能)。

template <class T, class = void> 
struct KeyValueTraits 
{ 
    typedef typename T::key_t key_t; 
    typedef typename T::value_t value_t; 
}; 

template <class MapIter> 
struct KeyValueTraits<MapIter, 
         typename std::enable_if< 
         sizeof(std::declval<MapIter>()->first) && 
         sizeof(std::declval<MapIter>()->second) 
         >::type> 
{ 
    typedef decltype(std::declval<MapIter>()->first) key_t; 
    typedef decltype(std::declval<MapIter>()->second) value_t; 
}; 
+0

n.m. - 對不起,但是...在地圖中,鍵的類型不是'key_type'?更多:不知道,但我懷疑OP要求'value_t',但他真的想'mapped_type' – max66

2

您使用可變參數模板參數,所以我想你可以接受一個C++ 11解決方案。

我建議以下(不是很好),基於模板專業化的解決方案。在計數

採取的主要類型,在std::map<>,是不是key_tkey_type和值的類型不是value_tmapped_type

#include <map> 

template <typename X> 
struct with_kt 
{ 
    template <typename Y = X> 
    static constexpr bool getValue (int, typename Y::key_type * = nullptr) 
    { return true; } 

    static constexpr bool getValue (long) 
    { return false; } 

    static constexpr bool value { getValue(0) }; 
}; 

template <typename T, bool = with_kt<T>::value> 
struct KeyValueTraits; 

template <typename T> 
struct KeyValueTraits<T, true> 
{ 
    using key_t = typename T::key_type; 
    using value_t = typename T::mapped_type; 
}; 

template <typename T> 
struct KeyValueTraits<T, false> 
{ 
    using pair_t = decltype(* std::declval<T>()); 

    using key_t = typename std::remove_const< 
         decltype(std::declval<pair_t>().first)>::type; 
    using value_t = decltype(std::declval<pair_t>().second); 
}; 


using mil = std::map<int,long>; 

int main() 
{ 
    static_assert(std::is_same<KeyValueTraits<mil>::key_t, 
           KeyValueTraits<mil::iterator>::key_t 
           >::value, "!"); 

    static_assert(std::is_same<KeyValueTraits<mil>::value_t, 
           KeyValueTraits<mil::iterator>::value_t 
           >::value, "!!"); 

    static_assert(std::is_same<KeyValueTraits<mil>::key_t, 
           KeyValueTraits<mil::const_iterator>::key_t 
           >::value, "!!!"); 

    static_assert(std::is_same<KeyValueTraits<mil>::key_t, 
           KeyValueTraits<mil::reverse_iterator>::key_t 
           >::value, "!!!!"); 

    static_assert(std::is_same<KeyValueTraits<mil>::key_t, 
           KeyValueTraits<mil::const_reverse_iterator>::key_t 
           >::value, "!!!!!"); 
} 
+0

感謝他的解決方案+1,剛糾正'mapped_type'錯誤。 – Dewfy