Thread: Recusively nested vector template: How to?

  1. #1
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587

    Recusively nested vector template: How to?

    1. How do I partially specialize a template(the second template of the two below)?
    2. Is there a better way to do this?

    T = type, D = dimensions
    Code:
    #include <vector>
    
    template<class T, size_t D>
    class vector : public vector<T, D - 1> {};
    
    template<class T, 1>
    class vector : public std::vector<T> {};

  2. #2
    Password:
    Join Date
    Dec 2009
    Location
    NC
    Posts
    587
    I think I got it.
    Code:
    #include <vector>
    
    template<class T, size_t D>
    class vector : public vector<T, D - 1> {};
    
    template<>
    class vector<class T, 1> : public std::vector<T> {};

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    What, what the...?
    vector is being derived from vector?! Are no alarm bells ringing for you?
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #4
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    There is actually nothing wrong with what he has done.

    The name of the template class is `vector'.

    The name of the class as implemented is `vector<T, D>'.

    The name of the class he is inheriting is `vector<T, D - 1>'.

    The two classes, `vector<T, D>' and `vector<T, D - 1>', share the same template but are different types. (The terminating case for the recursion allows this to resolve.)

    Soma

  5. #5
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    And the correct way to write the partial specialization to terminate the recursion is:

    Code:
    template <typename T>
    class vector<T, 1> : public std::vector<T>
    {};
    But I have to agree with iMalc that calling your multidimensional vector (if that is what you're trying to do) vector is probably not a good idea. Also, deriving from std::vector is not a good idea either.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I don't entirely see how that would make a multidimensional vector. A vector<T, 2> is a vector<T, 1> is a vector<T>.

    Perhaps something like that, where a multivector<T, x> is a vector<multivector<T, x - 1> >?

    Code:
    #include <vector>
    
    template <class T, unsigned D>
    class multivector;
    
    namespace detail {
    //metaclasses to determine parent of multivector<T, D>
    template <class T, unsigned D>
    struct mv_parent
    {
        typedef std::vector<multivector<T, D - 1> > type;
    };
    
    template <class T>
    struct mv_parent<T, 1>
    {
        typedef std::vector<T> type;
    };
    
    template <class T>
    struct mv_parent<T, 0>; //no such type
    }
    
    template <class Type, unsigned Dimensions>
    class multivector: private detail::mv_parent<Type, Dimensions>::type //private inheritance as recommended
    {
    public:
        typedef typename detail::mv_parent<Type, Dimensions>::type StorageType;
        typedef typename StorageType::size_type size_type;
        typedef typename StorageType::value_type value_type;
        typedef typename StorageType::iterator iterator;
        typedef typename StorageType::const_iterator const_iterator;
        typedef typename StorageType::reverse_iterator reverse_iterator;
        typedef typename StorageType::const_reverse_iterator const_reverse_iterator;
        //+ some other typedefs
    
        multivector() {}
        explicit multivector ( size_type n, const value_type& value = value_type()):
            StorageType(n, value)
        {}
        template <class InputIterator>
        multivector ( InputIterator first, InputIterator last ):
            StorageType(first, last)
        {}
    
        //expose all methods
        using StorageType::begin;
        using StorageType::end;
        using StorageType::rbegin;
        using StorageType::rend;
        using StorageType::size;
        using StorageType::max_size;
        using StorageType::resize;
        using StorageType::capacity;
        using StorageType::empty;
        using StorageType::reserve;
        using StorageType::operator[];
        using StorageType::at;
        using StorageType::front;
        using StorageType::back;
        using StorageType::assign;
        using StorageType::push_back;
        using StorageType::pop_back;
        using StorageType::insert;
        using StorageType::erase;
        using StorageType::swap;
        using StorageType::clear;
    };
    
    #include <iostream>
    int main()
    {
        multivector<int, 2> mvec;
        mvec.push_back(multivector<int, 1>(2, 3));
        mvec.push_back(multivector<int, 1>(4, 7));
        for (multivector<int, 2>::size_type i = 0; i != mvec.size(); ++i) {
            for (multivector<int, 1>::size_type j = 0; j != mvec.at(i).size(); ++j) {
                std::cout << mvec[i][j] << ' ';
            }
            std::cout << '\n';
        }
    }
    Last edited by anon; 02-08-2011 at 08:31 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by CornedBee View Post
    And the correct way to write the partial specialization to terminate the recursion is:

    Code:
    template <typename T>
    class vector<T, 1> : public std::vector<T>
    {};
    But I have to agree with iMalc that calling your multidimensional vector (if that is what you're trying to do) vector is probably not a good idea. Also, deriving from std::vector is not a good idea either.
    Yeah I was thinking of the base case that derives from std::vector.

    Code:
    #include <vector>
    using namespace std;
    vector<int, 2> v; // what do we have here...
    Well I'd be confused anyway
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Ah. I see.

    Code:
    Well I'd be confused anyway
    ^_^

    This is why I misinterpreted your comments.

    Soma

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problems with Nested Structures and Arrays of Structures
    By Ignoramus in forum C Programming
    Replies: 4
    Last Post: 03-02-2010, 01:24 AM
  2. Nested array vs. tree
    By KONI in forum Tech Board
    Replies: 1
    Last Post: 06-07-2007, 04:43 AM
  3. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  4. nested switch issue
    By fsu_altek in forum C Programming
    Replies: 3
    Last Post: 02-15-2006, 10:29 PM
  5. Nested Classes
    By manofsteel972 in forum C++ Programming
    Replies: 4
    Last Post: 11-21-2004, 11:57 AM