1

众所周知,operator=应该返回一个const引用来*this支持链接,但这只有在*this 可以用作类似值的右值时才有效。

编辑:很好,operator=应该返回一个非常量引用(作为ints 执行),我的意思是这*this需要rhs在分配中有意义。

我正在通过 C++ 类包装 name=value setter 函数的 C API,ApiWrapper并返回一个带重载operator[]的临时只写函数,但该 API 没有 getter 函数,因此实际上是只写函数。Proxyoperator=Proxy

ApiWrapper x;
x["a"] = x["b"] = 42;  // x["b"] = 42;      fine:  consumes 42, returns *this
                       // x["a"] = x["b"];  error: x["b"] does not have the value

在我看来,如果我返回一个 const 引用rhs而不是*thisfrom operator=,则链接可以正常工作。从概念上讲(省略了代理样板代码):

struct Proxy {
    template <typename T>
    T const& operator=(T const& rhs) const
    {
        ...         // pass rhs to the API but don't store it
        return rhs; // return rhs, not *this
    }
};

ApiWrapper x;
x["a"] = x["b"] = 42;  // x["b"] = 42;   fine: consumes and returns 42
                       // x["a"] = 42;   fine: consumes and returns 42

不过这让我很怀疑。rhs返回 const 引用而不是有什么奇怪的副作用*this吗?我唯一能想到的是,我将无法在表达式中使用它,(x["a"] = 42).doSomething()但无论如何我Proxy都不能支持这样的东西,因为它是只写的。还是仅仅禁止链接(例如通过返回)会更好void

编辑:即使Proxy不是像值一样,我认为支持分配是有道理的,它允许语法糖,如:

// this:                          // rather than:
ApiWrapper w;                     API * ptr = make_api_instance();
w["name"] = "Batman";             api_set_str(ptr, "name", "Batman");
w["age"]  = 42;                   api_set_int(ptr, "age", 42);
w["pi"]   = 3.14;                 api_set_double(ptr, "pi", 3.14);
4

2 回答 2

1

我认为最干净的解决方案是坚持使用标准习语。如果您以通常的方式使您的代理类可复制构造和可复制分配,这应该可以工作。像这样的东西:

struct Proxy
{
    Proxy(Proxy const & rhs)
    : // ...
    {
        // copy internal state of rhs
    }

    Proxy & operator=(Proxy const & rhs)
    {
        // copy internal state of rhs
        return *this;
    }

    template <typename T>
    Proxy & operator=(T const & rhs)
    {
        // ... perform T-specific operations ... #1
        return *this;
    }
};

另一个好处是,在#1 的第一个分配必须执行的任何“通用逻辑”都不需要在每个后续分配中重复。

于 2013-05-25T12:08:19.837 回答
0

我认为你的方法是有道理的。只是为了检查我是否正确理解了您的问题,该结构可能如下所示:

struct Proxy {
    template <typename T>
    T const& operator=(T const& rhs) const
    {
        send_to_abi(rhs);
        return rhs;
    }
};

正如您所说,由于 Proxy 不存储rhs任何地方,并且我假设不receive_from_abi存在任何功能,因此返回*this将不起作用 - 在这种情况下不会传播数字。正如评论指出的那样,某些行为(例如)(a=3)=3不起作用,但这并不令人惊讶。

编辑:正如评论所指出的,如果rhs是暂时的,这种方法是危险的。这可以通过返回一个副本来解决:

struct Proxy {
    template <typename T>
    T operator=(T const& rhs) const
    {
        send_to_abi(rhs);
        return rhs;
    }
};

这可能看起来很昂贵a["a"] = a["b"] = a["c"] = foo,看起来会涉及 3 个副本。但是这些应该可以通过通用的编译器优化来避免。

于 2013-05-25T12:17:07.133 回答