背景
以下代码块出现在 Scott Meyers 的名著《Effective C++》第 3 条中:
class TextBlock {
public:
...
const char& operator[](std::size_t position) const
{
... // do bounds checking
... // log access data
... // verify data integrity
return text[position];
}
char& operator[](std::size_t position)
{
... // do bounds checking
... // log access data
... // verify data integrity
return text[position];
}
...
private:
std::string text;
};
作者指出,在上述实现中,const
和非const
重载的内容本质上是相同的。为了避免代码重复,可以这样简化:
class TextBlock {
public:
...
const char& operator[](std::size_t position) const // the same as before
{
...
...
...
return text[position];
}
char& operator[](std::size_t position) // now just calls const op[]
{
return // cast away const on
const_cast<char&>( // op[]'s return type;
static_cast<const TextBlock&>(*this) // add const to *this's type;
[position] // call const version of op[]
);
}
...
private:
std::string text;
};
问题
我的问题是:
我们什么时候需要一个重载 for
const T&
和另一个 forT&&
?(这里,T
可能是模板参数或类类型,所以T&&
可能是也可能不是通用引用)我可以看到在标准库中,许多类都提供了这两种重载。例子是std::pair
and的构造函数std::tuple
,有大量的重载。(好的,我知道在函数中,一个是复制构造函数,一个是移动构造函数。)是否有类似的技巧来共享
const T&
和T&&
重载的实现?我的意思是,如果const T&&
重载返回一个复制构造的对象,而T&&
重载返回的是移动构造的对象,那么在共享实现之后,这个属性必须仍然成立。(就像上面的技巧:const
returnconst
and non-const
return non-const
,在实现共享之前和之后)
谢谢!
澄清
我指的两个重载应该如下所示:
Gadget f(Widget const& w);
Gadget f(Widget&& w);
它与通过右值引用返回无关,即:
Widget&& g(/* ... */);
(顺便说一下,这个问题在我之前的帖子中已经解决了)
在f()
上面,如果Gadget
既可以复制构造又可以移动构造,则没有办法(除了阅读实现)来判断返回值是复制构造还是移动构造。与返回值优化(RVO)/命名返回值优化(NRVO)无关。(见我之前的帖子)