繁体   English   中英

确定C ++函数中的左值和右值

[英]Determine lvalue and rvalue in C++ function

更新:我修改了一些地方,现在问题已经发生了某些变化。

我正在写一个C ++类。 喜欢:

class qqq{
    map<int,int> core;
    //......
    int& operator[](int n){return core[n];};
};
int main(){
    qqq a;
    a[3]=7;a[5]=0;//Case a
    int b=a[3];//Case b
    return 0;
}

虽然情况A和情况B调用相同的函数(重载运算符),但情况a用作左值,而情况b用作右值。

出于某种原因,我想要的是,如果将0传递给[5],则删除核心中的节点5。 喜欢:

int& operator[](int n){
    if(CASE A && THE VALUE PASSED TO IT IS 0)
        core.erase(core.find(n));
    else
        return core[n];
}

也许我的描述不准确。

您必须始终返回一个值,该值可用作赋值表达式中的左值。 因此,我建议使用garbage int变量。 我将garbage声明为静态因为我们只需要这个变量的一个实例而我们不关心它的值。

例如,

 class qqq{
    static int garbage;
    map<int,int> core;
    //......

    int& operator[](int n){
        if(CASE A && THE VALUE PASSED TO IT IS 0)
            return garbage;
        else
            return core[n];
    }
};

但是,此解决方案在我看来令人困惑,因为行为完全根据您在方括号中指定的内容而更改。 如果输入中传递的值不正确,我可能会抛出异常。

*编辑*

我认为你使用[]运算符使问题复杂化了。 您可以使用setter和getter轻松解决问题。 例如 :

int set(int index, int value){
    if( value == 0)
        core.erase(core.find(index));
    else
        return core[index];
}

int get(int index) {
 return core[index];
}

[]仅允许返回引用,您不知道赋值中使用的值是什么。

以下是注释中提到的代理模式的实现。

就个人而言,我不使用它,我的地图包含在根本不提供operator[]中,而是有.get(key, default) .init(key) .setdefault(key, default) .init(key).setdefault(key, default)等等取决于班级。

// This code is C++11 but it's not essential to the problem.
// The current code calls copy constructors more than necessary.
#include <map>

#include <cassert>


template<class K, class V>
struct zero_map
{
    struct proxy
    {
        std::map<K, V> *container;
        K key;

        operator V()
        {
            auto it = container->find(key);
            if (it == container->end())
                return V();
            return *it;
        }
        void operator = (V value)
        {
            if (value == V())
            {
                container->erase(key);
            }
            else
            {
                // probably should use .insert() and conditionally assign
                (*container)[key] = value;
            }
        }
    };

    std::map<K, V> _inner;

    proxy operator[](K k)
    {
        return proxy{&_inner, k};
    }
};

int main()
{
    zero_map<int, int> foo;
    assert (foo._inner.size() == 0);
    foo[1] = 0;
    assert (foo._inner.size() == 0);
    foo[0] = 1;
    assert (foo._inner.size() == 1);
    foo[0] = 0;
    assert (foo._inner.size() == 0);
}

正如评论所说,使用代理类。

template<typename T, size_t BadIndex>
class Element{ // please use a more meaningful name
    public:
        Element(const size_t index): index(index){}

        operator T& (){return value;}
        operator T const&() const{return value;}

        T &operator =(const T &rhs){
            if(index != BadIndex)
                value = rhs;
            return value;
        }

        operator T const&() const{return value;}
        operator T&(){return value;}

    private:
        T value;
        const size_t index;
};

class qqq{
    public:
        std::map<int, Element<int, 5>> core;

        Element<int> &operator [](size_t index){
            auto itt = core.find(index);
            if(itt == core.end()){
                core.emplace(index, index);
                itt = core.find(index);
            }
            return (*itt).second;
        }
};

这应该工作,但5将总是给你一个垃圾结果。

你的问题现在很清楚,遗憾的是你无法做到这一点就是C ++。 operator[]不是getter和setter:它只能返回一个引用,并且该引用仅用于单独的assignement。 在操作员返回其参考时,您无法知道将用于分配的值,并且您几乎不知道如何使用参考。

恕我直言,你需要的是更多:

int getCore(int i) {
    return core[i];
}

void setCore(int i, int newval) {
    if (newval == 0) {
        core.erase(core.find(i));
    }
    else {
        core[i] == newval;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM