c++ - View class into a container -


i'm trying write class view serve view container, (a sparse matrix class, should unimportant question).

view should contain references (e.g. std::reference_wrapper) selection of elements in container, , have methods returning references elements, assignment operator making 1 block equal another.

my problem want view able take values in addition references: both constructed values non-reference instance used in assignments, , assign values single elements in reference instance.

an mve of code far is:

#include <array>  template<typename t, size_t size> class view {      private:         std::array<t, size> _values;      public:         view(const std::array<t, size> & values)             : _values{ values } { }         // ----------         view<t, size> & operator=(const view<t, size> & other)         {             ( size_t = 0; < size; ++i ) {                 this->get(i) = other.get(i);             }             return *this;         }         // ----------         t & get(size_t idx)         {             return _values.at(idx);         }         const t & get(size_t idx) const         {             return _values.at(idx);         }  }; 

it can used this:

#include <functional> #include <iostream>  int main() {     int values[5] = { 1, 2, 3, 4, 5 };      view<int, 2> v1{         {values[0], values[1]}     };     view<std::reference_wrapper<int>, 2> v2{         {values[3], values[4]}     };      // works      v1.get(0) = 10;  // can assign non reference `view<int, size>`,                      // works intended      v2.get(0) += 9;  // can increment through reference wrappers,                      // works intended      // not work      // v2 = v1;  // nether of these work, there no conversion     // v1 = v2;  // between `view<std::reference_wrapper<int>, size>`                  // , `view<int, size>`. first expression                  // of interest      // v2.get(1) = 10;     // doesn't work return                            // `std::reference_wrapper<int>`, not                            // reference `int`     v2.get(1).get() = 10;  // works work-around                            // problem, feels clunky, ,                            // makes interface between 2 types                            // different      ( size_t = 0; < 2; ++i ) {         std::cout << v1.get(i) << " ";     }     std::cout << std::endl;     ( size_t = 0; < 5; ++i ) {         std::cout << values[i] << " ";     }     std::cout << std::endl; } 

this should output:

10 2 1 2 3 13 10 

i'm using clang++ compile on ubuntu 15.10.


so specifically,

  1. how should implement assignment operator allow view<t, size> , view<std::reference_wrapper<t>, size> assigned each other (or @ least former assigned latter). creating 2 versions

    view<t, size> & operator=(const view<t, size> & other); view<t, size> & operator=(     const view<std::reference_wrapper<t>, size> & other); 

    does not work, (as view<std::reference_wrapper<t>, size> need view<std::reference_wrapper<std::reference_wrapper<t> >, size> second overload).

  2. how can write get(size_t idx) methods such return t & bothview<t, size> , view<std::reference_wrapper<t>, size>?

i have feeling can accomplished using templates somehow, i'm still quite new template programming i'm bit lost.

here way make get() return t& t , std::reference_wrapper<t>:

template <typename t> struct get_value_type {     using type = t; };  template <typename t> struct get_value_type<std::reference_wrapper<t>> {     using type = t; };  template<typename t, size_t size> class view {     using value_type = typename get_value_type<t>::type;      value_type & get(size_t idx) {         return _values.at(idx);     }      const value_type & get(size_t idx) const {         return _values.at(idx);     } }; 

the get_value_type template obtain t both t , std::reference_wrapper<t>, change return type of get() value_type, , since std::reference_wrapper<t> implicitly convertible t& works.

now have access value_type, can use create 2 operator=:

view& operator= (const view<value_type, size> & other) {     (size_t = 0; < size; ++i) {         this->get(i) = other.get(i);     }     return *this; }  view& operator=(const view<std::reference_wrapper<value_type>, size> & other) {     (size_t = 0; < size; ++i) {         this->get(i) = other.get(i);     }     return *this; } 

in case want allow assignment different view (e.g. view of int view of double), use templated version:

template <typename u> view<t, size> & operator=(const view<u, size> & other) {     (size_t = 0; < size; ++i) {         this->get(i) = other.get(i);     }     return *this; } 

a small addition may bit off-topic instead of having std::array attribute, inherit std::array following:

template<typename t, size_t size> struct view: public std::array<t, size> {      using array_type = std::array<t, size>;     using value_type = typename get_value_type<t>::type;      view (std::array<t, size> const& values) : array_type (values) { }      view& operator=(const view<value_type, size> & other) {         (size_t = 0; < size; ++i) {             (*this)[i] = other[i];         }         return *this;     }      view& operator=(const view<std::reference_wrapper<value_type>, size> & other) {         (size_t = 0; < size; ++i) {             (*this)[i] = other[i];         }         return *this;     }       value_type & operator[](size_t idx) {         return array_type::operator[](idx);     }       const value_type & operator[](size_t idx) const {         return array_type::operator[](idx);     }  }; 

this allow use lot of stuff standard library on view without having redefine anything.


Comments

Popular posts from this blog

sql - invalid in the select list because it is not contained in either an aggregate function -

Angularjs unit testing - ng-disabled not working when adding text to textarea -

How to start daemon on android by adb -