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,
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 versionsview<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>
needview<std::reference_wrapper<std::reference_wrapper<t> >, size>
second overload).- how can write
get(size_t idx)
methods such returnt &
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
Post a Comment