gpt4 book ai didi

c++ - const 左值 (const T&) 和右值 (T&&) 重载的共享实现 : just like what is done for const and non-const overloads

转载 作者:搜寻专家 更新时间:2023-10-31 02:23:24 31 4
gpt4 key购买 nike

背景

以下代码块出现在 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;
};

问题

我的问题是:

  • 我们什么时候需要为 const T& 和另一个为 T&& 重载? (这里,T可能是模板参数,也可能是类类型,所以T&&可能是通用引用,也可能不是通用引用)我看到在标准库中,很多类提供两个重载。示例是 std::pair 的构造函数和 std::tuple ,有很多过载。 (好吧,我知道在函数中,其中一个是复制构造函数,其中一个是移动构造函数。)

  • 是否有类似的技巧来共享 const T&T&& 重载的实现?我的意思是,如果 const T&& 重载返回一个复制构造的对象,而 T&& 重载返回一个移动构造的对象,在共享实现之后,这个属性必须仍然持有。 (就像上面的技巧:const 返回 const 而非 const 返回非 const,之前和实现分享后)

谢谢!

说明

我指的两个重载应该是这样的:

Gadget f(Widget const& w);
Gadget f(Widget&& w);

它与通过右值引用返回无关,即:

Widget&& g(/* ... */);

(顺便说一句,这个问题在 my previous post 中得到了解决)

在上面的 f() 中,如果 Gadget 既是可复制构造的又是可移动构造的,则没有办法(除了读取实现)判断是否返回值是复制构造的或移动构造的。与返回值优化(RVO)/命名返回值优化(NRVO)无关。 (参见 my previous post)

引用资料

Effective C++

std::pair::pair

std::tuple::tuple

When is it a good time to return by rvalue references?

最佳答案

• When shall we need an overload for const T& and another for T&&?

基本上,当移动可以提高性能时,还应该有一个移动构造函数。这同样适用于您需要昂贵拷贝的功能。

在您的示例中,您返回对 char 的引用,但是不建议同时设置一个返回 右值引用的函数。相反,按值返回并依赖于编译器应用 RVO 的能力(参见例如 here )

•Is there a similar trick to share the implementations for the const T& and T&& overloads?

我经常发现使用通用引用(我很懒)来设置构造函数或函数很有用,例如

struct MyClass
{
template<typename T /*, here possibly use SFINAE to allow only for certain types */>
MyClass(T&& _t) : t(std::forward<T>(_t)) {}
private:
SomeType t;
};

编辑:关于您的更新:如果您的函数 f 中有昂贵的 Widget 拷贝,建议您也提供一个重载 Widget&&

Gadget f(Widget const& w)
{
Widget temp = w; //expensive copy
}
Gadget f(Widget&& w)
{
Widget temp = std::move(w); //move
}

您可以使用这样的函数模板将这两个函数结合起来

template<typename WidgetType
// possibly drop that SFINAE stuff
// (as it is already checked in the first assignment)
, typename std::enable_if<std::is_convertible<std::remove_reference_t<WidgetType>, Widget>::value> >
Gadget(WidgetType&& w)
{
Widget temp = std::forward<WidgetType>(w);
//or
std::remove_reference_t<WidgetType> temp2 = std::forward<WidgetType>(w);
}

...我没有说它更好 ;-).


编辑 2:另见 this thread ,它更彻底地解决了您的问题。

关于c++ - const 左值 (const T&) 和右值 (T&&) 重载的共享实现 : just like what is done for const and non-const overloads,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29346472/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com