简体   繁体   English

std :: map的所有迭代器的模板特化

[英]template specialization for all iterators of std::map

I have traits class, saying: 我有特质课,说:

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

Now I would like to declare specialization of this traits for all iterators of std::map 现在我想为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;
};

Compiler raises an error: 编译器引发错误:

error C2764: 'Args': template parameter not used or deducible in partial specialization 错误C2764:'Args':模板参数未在部分特化中使用或推导

So how to declare traits-type for all possible std::map<...>::iterator ? 那么如何为所有可能的std::map<...>::iterator声明traits-type?

You use variadic template parameters, so I suppose you can accept a C++11 solution. 您使用可变参数模板参数,所以我想您可以接受C ++ 11解决方案。

I propose the following (not really great), based on template specialization, solution. 基于模板专业化,解决方案,我提出以下(不是很好)。

Take in count that the type of the key, in std::map<> , isn't key_t but key_type and that the type of the value isn't value_t but mapped_type . key_t ,在std::map<>键的类型不是key_t而是key_type并且值的类型不是value_t而是mapped_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, "!!!!!");
 }

Here's one possible solution (it changes the KeyValueTraits template signature because it doesn't seem possible otherwise). 这是一种可能的解决方案(它改变了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;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM