C++ 包装类常量正确性问题

C++ 包装类常量正确性问题,c++,c++11,constants,wrapper,const-correctness,C++,C++11,Constants,Wrapper,Const Correctness,我试图围绕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

我试图围绕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;
}
intmain()
{
Json::Value realValue;
包装器w(真实值)

对于(const auto&i:w[“numberArray”]){cout两个运算符[]的返回类型是否都错了?它应该分别为Impl和/const Impl&?

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

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

一般来说,
const\u迭代器
iterator
是一个独立的类。我看不出你的
包装器
有什么不同

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

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

但这并不能阻止任何人将返回值复制到非常量
包装器
对象中,并使用它来变异
Impl

不一定。看起来OP依赖于对包装器的隐式转换。嘿,我在Zack的评论后捕捉到了它,但同时你正在编写答案:)