c++23 的“扣除此”功能是否应该与模板函数一起使用?

Should c++23's "deducting this" feature be used with template function?

提问人:lk.c 提问时间:11/5/2023 最后编辑:lk.c 更新时间:11/5/2023 访问量:113

问:

我正在专门阅读这篇文章 https://devblogs.microsoft.com/cppblog/cpp23-deducing-this/

class cat {
    ...
    //After
    template <class Self>
    auto&& get_held_toy(this Self&& self) {
        return self.held_toy_;
    }

    //After + forwarding
    template <class Self>
    auto&& get_held_toy(this Self&& self) {
        return std::forward<Self>(self).held_toy_;
    }
};

我尝试了以下代码,它仍然可以编译。在 Microsoft 博客的示例中使用模板功能有什么具体原因吗?

戈德博尔特

// turn on c++23
class cat {
    ...
    //After + forwarding
    auto&& get_held_toy(this cat&& self) {
        return std::forward<Self>(self).held_toy_;
    }
};
++ 的 C++23

评论

0赞 StoryTeller - Unslander Monica 11/5/2023
它不能是一个常规函数,因为对于不同的参数总是有不同的类型,这将影响生成的代码 - >它实际上是一个模板。self
2赞 Nicol Bolas 11/5/2023
足够。。。做什么?此代码的存在是有目的的。你需要知道这个目的是什么。

答:

3赞 Artyer 11/5/2023 #1

通过此声明:

auto&& get_held_toy(this cat&& self) {

显式对象参数始终具有类型(即右值引用),因此只能在右值上调用此函数:cat&&

auto c = cat{};
// c.get_held_toy();  // error
std::move(c).get_held_toy();
cat{}.get_held_toy();

这与以下基本相同:

auto&& get_held_toy() && {

它有用途,但这不是“推导”(它只是一个显式的对象参数)。this

真正的魔力:

template <class Self>
auto&& get_held_toy(this Self&& self) {

// Or
auto&& get_held_toy(this auto&& self) {

对象参数的类型,曾经是“”,可以从它的调用方式中推断出来(因此是“推断”):*thisthis

auto c = cat{};
toy_type& x = c.get_held_toy();  // mutable lvalue
const toy_type& y = std::as_const(c).get_held_toy();  // const lvalue
toy_type&& z = std::move(c).get_held_toy();  // xvalue

无需编写 3 个不同的重载。

0赞 Swift - Friday Pie 11/5/2023 #2

首先,允许确定它所调用的对象的实际限定符。一个定义适用于所有可能的重载,而不会引起歧义声明。对于模板函数是转发参考。如果删除模板,则将此函数限制为 xvalue\prvalue 函数。它允许这种类型的循环行为:this Self&&

class cat {
protected:
    ball held_toy_;
public:

    //After + forwarding
    template <class Self>
    auto&& get_held_toy(this Self&& self) {
        return std::forward<Self>(self).held_toy_;
    }
};

class displacer :  public cat
{
protected:
   player held_toy_;
   friend class cat;
};

int main()
{
    cat       mew;
    displacer boo;
    std::cout << typeid(mew.get_held_toy()).name() << std::endl;
    std::cout << typeid(cat().get_held_toy()).name() << std::endl;
    std::cout << typeid(boo.get_held_toy()).name() << std::endl; // displacer::held_toy_
}

其次,在 - in not 或 , 替换失败的情况下,你定义它的方式格式不正确。std::forward<Self>(self).held_toy_;Selfcatdisplacerstd::forward