带有模板容器的协变返回类型

发布于 2024-11-06 18:54:05 字数 419 浏览 1 评论 0原文

是否可以进行以下工作?基本上我想要 Ptr成为 Ptr 可接受的返回类型替代。

template<typename T>
class Ptr {
public:
    explicit Ptr (T * ptr) : ptr(ptr) {}
    T * ptr;
};


class A {
    virtual Ptr<A> foo () {
        return Ptr<A>(NULL);
    }
};

class B : public A {
    virtual Ptr<B> foo () { // BAD! Ptr<B> is not compatable
        return Ptr<B>(NULL);
    }
};

Is it possible to make the following work? Basically I want Ptr<B> to be an acceptable return type replacement for Ptr<A>.

template<typename T>
class Ptr {
public:
    explicit Ptr (T * ptr) : ptr(ptr) {}
    T * ptr;
};


class A {
    virtual Ptr<A> foo () {
        return Ptr<A>(NULL);
    }
};

class B : public A {
    virtual Ptr<B> foo () { // BAD! Ptr<B> is not compatable
        return Ptr<B>(NULL);
    }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦太阳 2024-11-13 18:54:05

您可以使用奇怪的重复模板来用模板函数返回替换虚拟函数重载。以下文章可能会有所帮助:

http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

另请检查下面的代码:

template <class C_>
class A_Base {
    Ptr<C_> foo() {
        return static_cast<C_*>(this)->foo_impl();
    }
}

class A : public A_Base<A> {
    Ptr<A> foo_impl() { return Ptr<A>(NULL); }
}

class B : public A_Base<B> {
   Ptr<B> foo_impl() { return Ptr<B>(NULL); }
}

Your can use curiously recurring templates to replace virtual function overloads with template function returns. The following article might help:

http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

Also check the following code:

template <class C_>
class A_Base {
    Ptr<C_> foo() {
        return static_cast<C_*>(this)->foo_impl();
    }
}

class A : public A_Base<A> {
    Ptr<A> foo_impl() { return Ptr<A>(NULL); }
}

class B : public A_Base<B> {
   Ptr<B> foo_impl() { return Ptr<B>(NULL); }
}
只是在用心讲痛 2024-11-13 18:54:05

根据标准:

重写函数的返回类型应与被重写函数的返回类型相同或与函数的类协变。如果函数 D::f 重写函数 B::f,则函数的返回类型在满足以下条件的情况下是协变的:

  • 两者都是指向类的指针或对类的引用
  • B::f 返回类型中的类与 D::f 返回类型中的类是同一类,或者是 D::f 返回类型中的类的明确直接或间接基类,并且可以在 D 中访问
  • 指针或引用都具有相同的cv 限定和 D::f 返回类型中的类类型具有与 B::f 返回类型中的类类型相同或更少的 cv 限定。

因此,在您的示例中,返回类型并不是真正协变的(它们不是指针也不是引用),而且 PtrPtr 是不相关的类型。

因此,保持 foo 为虚拟并在 A 中返回 Ptr 并在 B 中返回 Ptr 是不可能的。如果您可以/愿意放弃虚拟,那么您可以使用 Cem Kalyoncu 提案或其变体中的某些内容。

According to the standard:

The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:

  • both are pointers to classes or references to classes
  • the class in the return type of B::f is the same class as the class in the return type of D::f or, is an unambiguous direct or indirect base class of the class in the return type of D::f and is accessible in D
  • both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.

So in your example the return types are not really covariant (they are not pointers nor references) and moreover Ptr<B> and Ptr<A> are unrelated types.

So keeping foo virtual and returning Ptr<A> in A and Ptr<B> in B is not possible. If you can/are willing to drop virtual than you can use something in the lines of Cem Kalyoncu's proposal or a variation of it.

傲世九天 2024-11-13 18:54:05

你可以尝试这样的事情:

template<class T> class Ptr
{
...
};

template<class T> class A
{
    virtual Ptr<T> foo();
};

class B : public A<B>
{
    virtual Ptr<B> foo();
};

You could try something like this:

template<class T> class Ptr
{
...
};

template<class T> class A
{
    virtual Ptr<T> foo();
};

class B : public A<B>
{
    virtual Ptr<B> foo();
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文