2013-07-03 86 views
1

我試圖圍繞JsonCpp的Json::Value創建一個包裝。包裝類const正確性問題

我有一個命名空間global我在那裏的功能,Json::Value&參數的工作。我想爲這些函數創建一個語法上更令人愉快的包裝類。

這是一個簡單的例子。

// Impl is a typedef for Json::Value, from JsonCpp 

namespace global 
{ 
    Impl& getChild(Impl& mImpl, const std::string& mName) { return mImpl[mName]; } 
    const Impl& getChildConst(const Impl& mImpl, const std::string& mName) { return mImpl[mName]; } 

    Impl::iterator beginNonConst(Impl& mRoot)   { return mRoot.begin(); } 
    Impl::iterator endNonConst(Impl& mRoot)    { return mRoot.end(); } 
    Impl::const_iterator beginConst(const Impl& mRoot) { return mRoot.begin(); } 
    Impl::const_iterator endConst(const Impl& mRoot) { return mRoot.end(); } 
} 

class Wrapper 
{ 
    private: 
     Impl& impl; 

    public: 
     Wrapper(Impl& mImpl) : impl(mImpl) { } 

     Wrapper operator[](const std::string& mName) { return global::getChild(impl, mName); } 

     // Error here 
     // no known conversion for argument 1 from 'const Impl {aka const Json::Value}' to 'Impl& {aka Json::Value&}' 
     const Wrapper operator[](const std::string& mName) const { return global::getChildConst(impl, mName); } 

     Impl::iterator begin()    { return global::beginNonConst(impl); } 
     Impl::iterator end()    { return global::endNonConst(impl); } 
     Impl::const_iterator begin() const { return global::beginConst(impl); } 
     Impl::const_iterator end() const { return global::endConst(impl); } 
}; 

這就是我希望能夠編譯:

int main() 
{ 
    Json::Value realValue; 
    Wrapper w(realValue) 
    for(const auto& i : w["numberArray"]) { cout << i << endl; } 
    for(auto& i : w["numberArray"]) { i += 100; } 

    // assert that changes have been made to realValue through the wrapper 

    return 0; 
} 

回答

3

A Wrapper有一個Impl&類型的成員。使Wrapper對象const僅更改其成員的頂級const(對引用不做任何操作,引用已經不可重新綁定),甚至只有在構造函數完成後才生效。

您需要一個類型爲const Impl&的成員,而const Wrapper不需要。編譯器正確地防止您丟失const限定符並將const Impl&傳遞給Wrapper::Wrapper(Impl&),這可能會改變它的參數。

通常const_iterator是與iterator分開的類。我看不出爲什麼你的Wrapper會有任何不同。

作爲一個短期的解決方案,你可以使用

const Wrapper operator[](const std::string& mName) const { return global::getChild(impl, mName); } 

但這並不阻止任何人複製返回值到非const對象Wrapper,並用它來突變的Impl

+0

嘿,我剛剛在Zack的評論中發現了它,但是你正在寫你的答案:) – Alex1985

0

是不是同時返回operator []的錯誤的類型?它應該分別爲Impl &/const Impl &?

+0

不一定。它看起來像OP是依靠隱式轉換爲Wrapper。 –