只写对象的链接操作符= - OK返回rhs而不是*this
Chaining operator= for write-only objects - OK to return rhs instead of *this?
众所周知,operator=
应该返回一个const对*this
的引用来支持链接,但这只适用于*this
可以用作右值与值类似的情况。
编辑:好的,operator=
应该返回一个非const引用(做int
s),我的意思是*this
需要在赋值中成为一个有意义的rhs
。
我包装一个C API的名称=值设置函数通过一个c++类ApiWrapper
与operator[]
返回一个临时只写Proxy
与重载operator=
,但API没有getter函数,所以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
在我看来,如果我从operator=
返回一个const引用到rhs
而不是*this
,链接将工作得很好。概念上(省略代理样板代码):
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
这让我怀疑。是否有任何奇怪的副作用从返回一个const引用rhs
而不是*this
?我唯一能想到的是,我将无法在像(x["a"] = 42).doSomething()
这样的表达式中使用它,但我的Proxy
无论如何都不能支持这样的东西,因为它是只写的。或者干脆不允许链接(例如通过返回void
)会更好吗?
Edit:即使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);
我认为最干净的解决方案是坚持使用标准习惯用法。如果您以通常的方式使代理类具有可复制构造性和可复制赋值性,这应该可以工作。像这样:
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的第一个赋值中必须执行什么"泛型逻辑",都不需要在每个后续赋值中重复。
我认为你的方法很有道理。只是为了检查我是否正确理解了你的问题,结构可以看起来像这样:
struct Proxy {
template <typename T>
T const& operator=(T const& rhs) const
{
send_to_abi(rhs);
return rhs;
}
};
正如你所说,由于代理不存储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个副本。但是这些应该可以通过一个通用的编译器优化来避免。
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 什么时候在C++中返回常量引用是个好主意
- 你能重载对象变量名本身返回的内容吗
- 为什么 Serial.println(<char[]>);返回随机字符?
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何获取std::result_of函数的返回类型
- QueryWorkingSet总是返回false
- (C++)分析树以计算返回错误值的简单算术表达式
- 访问者访问变体并返回不同类型时出错
- 如何返回一个类的两个对象相加的结果
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- lower_bound()返回最后一个元素
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 如何取消对nullptr的屏蔽,返回正确的对象
- 奇怪的结构&GCC&clang(void*返回类型)
- 架构决策:返回std::future还是提供回调
- 从python中调用C++函数并获取返回值
- 通过友元函数重载运算符,并返回与rhs参数不同的类型
- 只写对象的链接操作符= - OK返回rhs而不是*this