Is there a way to forward declare covariance?

后端 未结 4 1463
别跟我提以往
别跟我提以往 2021-02-19 02:02

Suppose I have these abstract classes Foo and Bar:

class Foo;
class Bar;

class Foo
{
public:
  virtual Bar* bar() = 0;
};

class Bar
{         


        
相关标签:
4条回答
  • 2021-02-19 02:21

    Doesn't static polymorphism solve your problem? Feeding the base class with the derived class through template argument? So the base class will know the derivative Type and declare a proper virtual?

    0 讨论(0)
  • 2021-02-19 02:22

    How about this.

    template <class BarType>
    class Foo
    {
    public:
        virtual BarType* bar() = 0;
    };
    
    template <class FooType>
    class Bar
    {
    public:
        virtual FooType* foo() = 0;
    };
    
    class ConcreteBar;
    class ConcreteFoo : public Foo<ConcreteBar>
    {
    public:
        ConcreteBar* bar();
    };
    
    class ConcreteBar : public Bar<ConcreteFoo>
    {
    public:
        ConcreteFoo* foo();
    };
    
    0 讨论(0)
  • 2021-02-19 02:33

    You can fake it quite easily, but you lose the static type checking. If you replace the dynamic_casts by static_casts, you have what the compiler is using internally, but you have no dynamic nor static type check:

    class Foo;
    class Bar;
    
    class Foo
    {
    public:
      Bar* bar();
    protected:
      virtual Bar* doBar();
    };
    
    class Bar;
    {
    public:
      Foo* foo();
    public:
      virtual Foo* doFoo();
    };
    
    inline Bar* Foo::bar() { return doBar(); }
    inline Foo* Bar::foo() { return doFoo(); }
    
    class ConcreteFoo;
    class ConcreteBar;
    class ConcreteFoo : public Foo
    {
    public:
      ConcreteBar* bar();
    protected:
      Bar* doBar();
    };
    
    class ConcreteBar : public Bar
    {
    public:
       ConcreteFoo* foo();
    public:
       Foo* doFoo();
    };
    
    inline ConcreteBar* ConcreteFoo::bar() { return &dynamic_cast<ConcreteBar&>(*doBar()); }
    inline ConcreteFoo* ConcreteBar::foo() { return &dynamic_cast<ConcreteFoo&>(*doFoo()); }
    
    0 讨论(0)
  • 2021-02-19 02:42

    Covariance is based on inheritance diagram, so since you cannot declare

    class ConcreteBar : public Bar;
    

    hence no way to tell compiler about covariance.

    But you can do it with help of templates, declare ConcretFoo::bar as template and later bounding allows you solve this problem

    0 讨论(0)
提交回复
热议问题