2014-01-31 33 views
0

我正在研究一個圖像類,它可以使用不同像素佈局(RGB,RGBA,灰色,拜耳,...)的圖像。要訪問像素,可以撥打image.at<PixelType>(x,y),它返回一個「Accessor」。具體的Accessor實現依賴於模板參數。但是現在我遇到了一些關於const正確性的問題。數據訪問器類型的const正確性 - 更好的解決方案?

這裏是一個非常簡單化了實現這有望使得它明顯:

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; 
} 

正如你可以看到有一個非常量和常量執行at方法。根據常量,訪問器的模板參數設置爲truefalse。但是現在我有兩種不同的類型(const和non-const),每個訪問器/像素類型都有必要編寫一個轉換構造函數,否則main()函數中顯示的測試用例將不起作用。

現在的問題是: 有沒有更好的方法來實現這一目標?使用模板參數作爲const指示器感覺不好。使用Accessorconst Accessor會更好。另一方面,這與std-library與::iterator::const_iterator所做的相似。 任何人都有這種情況下的一些經驗?

+0

你可以做類似於標準容器對迭代器做什麼的事情,它有兩個不同的迭代器:'iterator'和'const_iterator',迫使程序員考慮使用哪個迭代器。不幸的是,程序員很少考慮它,即使'const_iterator'是最好的,也可以使用普通的'iterator'。 –

+0

@JoachimPileborg我試圖澄清,我認爲我的方法類似於std庫中的一個。任務是如果有更好的解決方案。 – Daniel

回答

2

你可以(過度)從具有兩個布爾州的任何值類型,而不是一概而論的參數:

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; 
}; 

顯然,這不是比你有什麼什麼不同,只是在另一種姿態:代替Accessor<false>Accessor<true>,您有Accessor<DataType>Accessor<DataType const>

好處是熟悉:所有的例如std::unique_ptr<T>std::shared_ptr<T>,std::reference_wrapper<T>(和甚至T*)表現相同的方式。特別是,這種家庭應該有希望延伸到編譯器錯誤,關於缺少從Accessor<DataType const>Accessor<DataType>的轉換,就像你不能從int const*轉換到int*一樣。

+0

感謝您的回答 - 特別是第二段明確指出,這種行爲並不是非典型的 – Daniel

相關問題