带有前向声明无效的using指令的循环依赖

问题描述 投票:3回答:2

我正在使用无法解决这种循环依赖性的代码库:

foo.h

class Foo
{
public:
  using Ptr = std::shared_ptr<Foo>;
  using ConstPtr = std::shared_ptr<const Foo>;

  void setter(const Bar::Ptr& bar_ptr) {};

private:
  Bar::WeakPtr bar_ptr_;
};

bar.h

class Bar
{
public:
  using Ptr = std::shared_ptr<Bar>;
  using ConstPtr = std::shared_ptr<const Bar>;
  using WeakPtr = std::weak_ptr<Bar>;

  Bar(Foo::ConstPtr foo_ptr) : foo_ptr_(std::move(foo_ptr)) {};

private:
  Foo::ConstPtr foo_ptr_;
};

以前是编译的,因为这里有一个外部头文件:

using FooPtr = std::shared_ptr<Foo>;
using FooConstPtr = std::shared_ptr<const Foo>;
using BarPtr = std::shared_ptr<Bar>;

但是由于追求一致性,所以我想使用Foo::PtrFoo::ConstPtrBar::Ptr。我有机会得到它吗?

Coliru

编辑:添加了Bar::WeakPtr,因为我以为自己已经遇到麻烦了,所以以前不见了。

c++ using circular-dependency forward-declaration
2个回答
2
投票

可以说这是C ++的不足。在不包括整个类定义的情况下,不能仅声明类的某些公共名称。在这种情况下,恐怕您的循环依赖关系无法解决-至少不会以某种将来不会以某种方式咬住您的方式解决。

但是,作为替代,请考虑在主题类之外使用模板定义。它会更改术语的顺序,但不会更改整体含义:

template<class T>
struct PtrStruct {
    using type = std::shared_ptr<T>;
};

template<class T>
using Ptr = typename PtrStruct<T>::type;

template<class T>
struct ConstPtrStruct {
    using type = std::shared_ptr<const T>;
};

template<class T>
using ConstPtr = typename PtrStruct<const T>::type;

在此设置下,您的Foo::Ptr变为Ptr<Foo>Foo::ConstPtr变为ConstPtr<Foo>。您仍然可以:

  • 在稍后阶段,在定义了std::shared_ptr的单个位置用不同的内容替换PtrStruct。只要使用的接口未更改,其余代码将无需更改即可编译。
  • PtrStruct专门设置为T,是否应该与其他设置不同。

0
投票

如果要追求一致性,请不要创建变形的结构。您可以尝试类似:


// Foo.h

class Bar;

class Foo
{
public:
  using BarPtr = std::shared_ptr<Bar>;

  void setter( BarPtr bar_ptr)
  {}
};


// Bar.h

class Foo;

class Bar
{
public:
  using ConstFooPtr=std::shared_ptr<const Foo>;

  Bar( ConstFooPtr foo_ptr)
      : foo_ptr_( std::move( foo_ptr))
  {}

private:
  ConstFooPtr foo_ptr_;
};

© www.soinside.com 2019 - 2024. All rights reserved.