我正在使用无法解决这种循环依赖性的代码库:
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::Ptr
,Foo::ConstPtr
,Bar::Ptr
。我有机会得到它吗?
编辑:添加了Bar::WeakPtr
,因为我以为自己已经遇到麻烦了,所以以前不见了。
可以说这是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
,是否应该与其他设置不同。如果要追求一致性,请不要创建变形的结构。您可以尝试类似:
// 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_;
};