实现返回 *this(协变返回类型)的“虚拟”方法

Implementing a "virtual" method returning *this (covariant return type)

提问人:einpoklum 提问时间:10/6/2022 最后编辑:Jan Schultkeeinpoklum 更新时间:9/24/2023 访问量:161

问:

我正在编写 C++ 类的层次结构,比方说 , 继承 , 继承 和 继承 。ABACADB

现在,所有这些类都必须有一个方法,其主体是:bar() &

{
    A::foo();
    return *this;
}

这是完全相同的代码,执行完全相同的操作 - 除了返回值的类型 - 它返回对类类型的左值引用。

现在,此方法的签名对于每个类都是不同的。但是 - 这本质上是相同的方法。问题是,按照目前的情况,我需要多次复制它的代码。如何避免这种代码重复?

我本来想用 CRTP 写一些 mixin,但当我进入细节时,它变得超级丑陋。

注意:在本例中,仅针对左值定义,以免涉及从右值返回的合法性问题。bar()*this

C++ 这个 虚函数 自引用 显式对象参数

评论

0赞 Henrique Bucher 10/6/2022
对不起,如果这听起来像是一个混蛋,但这有什么价值?你会用一些微不足道的东西(就像现在一样)来增加代码的复杂性,可能会影响性能,除了节省几行代码之外什么也得不到。
1赞 Öö Tiib 10/6/2022
阅读“协变返回类型”。
0赞 Remy Lebeau 10/6/2022
@einpoklum 以你所描述的方式实施真的没有任何好处。只需在 中实现一次,返回 ,如果调用者需要访问派生类,那么他们可以根据需要/返回值。bar()AA&static_castdynamic_cast
1赞 einpoklum 10/6/2022
@HenriqueBucher:这不适用于性能关键型代码,所以这无关紧要。我确实只想保存几行代码。如果我不能相对轻松地做到这一点,我只会忍受重复:-(
3赞 Raymond Chen 10/6/2022
今天,你必须我们CRTP。 在 C++23 中,您将能够使用“推导这个”:template<typename Final> struct A { Final& bar() { A::foo(); return static_cast<Final&>(*this); }}; template<typename Final> struct B : A<Final> {}; struct D: B<D>{};struct A { template<typename Self> Self& bar(this Self& self) { self.foo(); return self;} }; struct B : A{}; struct D : B{};

答:

2赞 Jarod42 10/6/2022 #1

正如 Raymond Chen 所评论的那样,c++23 可以推断出这一点,从而允许如下代码:

struct A
{
    template <typename Self>
    Self& bar(this Self& self) // Here self is the static type which calls bar
                               // so potentially the derived type
    {
        self.A::foo(); // or self.foo();
        return self;
    }
    // ...
};
struct B : A{};
struct C : A{};
struct D : B{};

但目前,CRTP 可能会有所帮助,例如:

struct A
{
    // ...
};


template <typename Derived, typename Base>
struct A_CRTP : Base
{
    Derived& bar()
    {
        A::foo();
        return static_cast<Derived&>(*this);
    }
    // ...
};
struct B : A_CRTP<B, A> {};
struct C : A_CRTP<C, A> {};
struct D : A_CRTP<D, B> {};