c++ - const-correctness of data-accessor types - better solution? -


i'm working on image-class makes possible work images different pixel layouts (rgb, rgba, gray, bayer, ...). access pixel it's possible call image.at<pixeltype>(x,y) returns "accessor". concrete accessor-implementation dependent on template argument. i've ran issues regarding const correctness.

here dumbed down implementation makes apparent:

template<bool constaccessor> class accessor { public:     typedef typename boost::mpl::if_c<constaccessor, const int, int>::type datatype;      accessor(datatype& data)      :data(data) {     }      accessor(accessor<false>& other)      : data(other.data) {     }      datatype& data; };   class image { public:     accessor<false> at(unsigned int x, unsigned int y) {         return accessor<false>(data);     }     accessor<true> at(unsigned int x, unsigned int y) const {         return accessor<true>(data);     }  private:     int data; };  int main() {     image img;     const image& cimg = img;      // accessor non-const     accessor<false> a1 = img.at(0, 0);       // accessor const...     accessor<true> a2 = a1;     // ... modifying value results in error     a2.data = 42;      // try convert accessor const non-const version     // ... results in error     accessor<false> a3 = a2;      return 0; } 

as can see there non-const , const implementation of at method. depending on constness template argument of accessor set true or false. i've got 2 different types (const , non-const) per accessor/pixel type makes necessary write conversion constructor because otherwise test-cases shown in main() function wouldn't work.

now question is: there better way achieve this? feels kind of bad use template argument const indicator. nicer use accessor , const accessor. on other hand similar std-library ::iterator , ::const_iterator. has experience such situations?

you can (over-)generalise parameter having 2 boolean states value type instead:

template<typename value> class accessor { public:         accessor(value& data)          : data(data)     {}      template<typename t, enableif<std::is_convertible<t&, value&>>...>     accessor(accessor<t> const& other)         : data(other.data)     {}      value& data; }; 

obviously isn’t different have, except under guise: instead of accessor<false> , accessor<true>, have accessor<datatype> , accessor<datatype const>.

the benefit familiarity: of e.g. std::unique_ptr<t>, std::shared_ptr<t>, std::reference_wrapper<t> (and t*) behave same way. in particular, famialiarity should extend compiler errors lack of conversion accessor<datatype const> accessor<datatype>, can’t convert int const* int*.


Comments

Popular posts from this blog

html - Sizing a high-res image (~8MB) to display entirely in a small div (circular, diameter 100px) -

java - IntelliJ - No such instance method -

identifier - Is it possible for an html5 document to have two ids? -