1

我正在尝试围绕 JsonCpp 的Json::Value.

我有一个命名空间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;
}
4

2 回答 2

3

AWrapper有一个类型为 的成员Impl&。使Wrapper对象const仅更改其成员的顶级const(对引用没有任何作用,引用已经不可重新绑定),甚至只有在构造函数完成后才会生效。

您需要一个具有 type 成员的类const Impl&const Wrapper但不需要。编译器正确地防止您丢失const限定符并将 a 传递const Impl&Wrapper::Wrapper(Impl&)它可能会改变其参数。

通常const_iterator是一个单独的类iteratorWrapper我看不出你有什么不同的理由。

作为短期解决方案,您可以使用

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

但这并不妨碍任何人将返回值复制到非常量Wrapper对象中并使用它来改变Impl.

于 2013-07-03T20:53:22.137 回答
0

两个 operator[] 的返回类型都不是错误的吗?应该分别是Impl&/const Impl&吧?

于 2013-07-03T20:43:57.077 回答