Candy Chiu
Candy Chiu

Reputation: 6679

How to wrap multi level raw pointers to give it container semantics

How can I wrap T** to give it std::vector<std::vector<T>> semantics? All solutions I have found so far address a single dimension.

The use case is to pass both T** and std::vector<std::vector<T>> to a function that consumes matrix data.

template<class RowIt>
void foo(RowIt rowFirst, RowIt rowLast) {
    // size doesn't handle dynamically allocated arrays        
    size_t columns = std::size(*rowFirst);     

    // second layer std::begin, std::end and iterator doesn't 
    // work for dynamically allocated arrays
    for (; rowFirst != rowLast; ++rowFirst) {
       auto colFirst = std::begin(rowFirst);
       auto colLast = std::end(rowFirst);
       for (; colFirst != colLast; ++colFirst) {
           // processing logic
       }
    }
}

I attempted to extend the single dimension solution to multi dimension. The problem I run into is

template<class T>
class view {
   T* data_;
};

view<view<T>> can't be composed from view<T>.

Upvotes: 1

Views: 79

Answers (1)

Caleth
Caleth

Reputation: 62809

You can add a partial specialisation for nested views.

template<class T>
class view {
   using pointer = T*;
   pointer data_;
};

template<class T>
class view<view<T>> {
   using pointer = typename view<T>::pointer *;
   pointer data_;
};

Or specify view::pointer via a traits class, if it is the only divergence from the primary template

template<class T>
class view_traits {
   using pointer = T*;
};

template<class T>
class view_traits<view<T>> {
   using pointer = typename view<T>::pointer *;
};

template<class T>
class view {
   using pointer = typename view_traits<T>::pointer;
   pointer data_;
   // other members use T unchanged
};

Upvotes: 1

Related Questions