2017-04-01 44 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