[英]const-correctness of data-accessor types - better solution?
I'm working on a image-class which makes it possible to work with images with different pixel layouts (RGB, RGBA, Gray, Bayer, ...). 我正在开发一个图像类,它可以处理具有不同像素布局(RGB,RGBA,灰色,拜耳等)的图像。 To access a pixel it's possible to call
image.at<PixelType>(x,y)
which returns an "Accessor". 要访问像素,可以调用
image.at<PixelType>(x,y)
,返回“访问者”。 The concrete Accessor-implementation is dependent on the template argument. 具体的Accessor实现依赖于模板参数。 But now i've ran into some issues regarding const correctness.
但是现在我遇到了一些关于const正确性的问题。
Here is a very dumbed down implementation which hopefully makes it 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;
// get accessor which is non-const
Accessor<false> a1 = img.at(0, 0);
// get a accessor which is const...
Accessor<true> a2 = a1;
// ... modifying a value results in an error
a2.data = 42;
// try to convert a accessor which is const to a non-const version
// ... results in an error
Accessor<false> a3 = a2;
return 0;
}
As you can see there is a non-const and a const implementation of the at
method. 如您所见,
at
方法有一个非const和一个const实现。 Depending on the constness the template argument of the accessor is set to true
or false
. 根据constness,访问者的模板参数设置为
true
或false
。 But now i've got two different types (const and non-const) per accessor/pixel type which makes it necessary to write a conversion constructor because otherwise the test-cases shown in the main()
function wouldn't work. 但是现在我有两种不同的类型(const和非const)每个访问器/像素类型,这使得有必要编写转换构造函数,因为否则
main()
函数中显示的测试用例将无法工作。
Now the question is: Is there a better way to achieve this? 现在的问题是:有没有更好的方法来实现这一目标? It feels kind of bad to use a template argument as const indicator.
使用模板参数作为const指示器感觉有点不好。 It would be much nicer to just use
Accessor
and const Accessor
. 使用
Accessor
和const Accessor
会好得多。 On the other hand this is similar to what the std-library does with ::iterator
and ::const_iterator
. 另一方面,这类似于std-library对
::iterator
和::const_iterator
。 Anyone has some experience with such situations? 任何人都有这种情况的经验吗?
You can (over-)generalise your parameter from having the two boolean states to any 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 this isn't any different than what you have, except under another guise: instead of Accessor<false>
and Accessor<true>
, you have Accessor<DataType>
and Accessor<DataType const>
. 显然这与你所拥有的没什么不同,除了另一种形式:不是
Accessor<false>
和Accessor<true>
,你有Accessor<DataType>
和Accessor<DataType const>
。
The benefit is familiarity: all of eg std::unique_ptr<T>
, std::shared_ptr<T>
, std::reference_wrapper<T>
(and even T*
) behave the same way. 好处是熟悉:所有例如
std::unique_ptr<T>
, std::shared_ptr<T>
, std::reference_wrapper<T>
(甚至T*
)的行为方式相同。 In particular, this famialiarity should hopefully extend to compiler errors about a lack of conversion from Accessor<DataType const>
to Accessor<DataType>
, much like you can't convert from int const*
to int*
. 特别是,这种家庭化应该有希望扩展到编译器错误,即从
Accessor<DataType const>
到Accessor<DataType>
的转换不足,就像你不能从int const*
转换为int*
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.