Changing value_type of a given STL container

前端 未结 3 1572
盖世英雄少女心
盖世英雄少女心 2021-01-06 17:26

Suppose, I\'ve a STL container type (not object), say vector. Now it\'s value_type is A, so I want to change it to <

3条回答
  •  清酒与你
    2021-01-06 18:18

    Just stumbled over this as I was trying to essentially solve the same problem. It can even be made to work without relying on the rebind type that is specific to std::allocator – the only requirement is that the rebound value type is the first template parameter of the respective classes. This is the case for all relevant STL classes (std::vector, std::set, std::list etc. as well as for example std::less and std::allocator).

    A pre-C++11 solution would look like this:

    template 
    struct rebind;
    
    template  class Container, class NewType>
    struct rebind, NewType>
    {
      typedef Container type;
    };
    
    template  class Container, class NewType>
    struct rebind, NewType>
    {
      typedef Container::type> type;
    };
    
    template  class Container, class NewType>
    struct rebind, NewType>
    {
      typedef Container::type, typename rebind::type> type;
    };
    
    // Continue for more parameters (A, B, C, ...)
    

    C++11 makes it a bit easier:

    template 
    struct rebind;
    
    template  class Container, class NewType>
    struct rebind, NewType>
    {
      typedef Container::type...> type;
    };
    

    In order to support std::array, the following can be added:

    template  class Container, class NewType>
    struct rebind, NewType>
    {
      typedef Container type;
    };
    

    The result can be used with just about any STL type:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include "rebind.h"
    
    // Make it all a bit more compact
    #define REBIND_DEMO(container, new_type)                \
      do {                                                  \
        container test;                                     \
        rebind::type test2;       \
        std::cout << typeid(test).name() << "\n";           \
        std::cout << typeid(test2).name() << "\n";          \
      } while (0)
    
    int main()
    {
      REBIND_DEMO(std::set, double);
      REBIND_DEMO(std::list, double);
      REBIND_DEMO(std::deque, double);
      REBIND_DEMO(std::queue, double);
      typedef std::array TestArray;
      REBIND_DEMO(TestArray, double);
      REBIND_DEMO(std::unordered_set, double);
    
      return 0;
    }
    

    Running this and piping the output through c++filt -t on a Linux system gives you

    std::set, std::allocator >
    std::set, std::allocator >
    std::list >
    std::list >
    std::deque >
    std::deque >
    std::queue > >
    std::queue > >
    std::array
    std::array
    std::unordered_set, std::equal_to, std::allocator >
    std::unordered_set, std::equal_to, std::allocator >
    

提交回复
热议问题