4

我可能已经到达这里来解决应该是一个简单的问题。我从这里开始这个问题: Getting type of base class at compile time

基本上我试图让类管理它自己的指针类型。我正在包装一个 C 库,其中一些结构中嵌入了引用计数,而另一些则没有。那些没有,我想使用shared_ptr。那些这样做的,我想使用 intrusive_ptr。我想避免依赖程序员的智慧来确保使用正确的包装器。最终,我想添加更多依赖此行为的功能,但我还没有。

@Yakk 提出了一个使用模板类型别名的有趣解决方案,我已经尝试实现它。不幸的是,我似乎无法解决循环引用以使编译器满意。我收到指向“使用指针=”行的“在嵌套名称说明符中命名的不完整类型'Test2'”错误。对于我对 Test::f() 的定义,我还得到了一个奇怪的“定义与返回类型中的声明不同”,但我怀疑一旦我解决了第一个错误,它可能会自行解决。

我在这种错误类型上找到的大多数参考资料都涉及头文件的排序,但即使所有内容都在一个文件中,我也无法弄清楚如何排序以使这个问题消失。

有任何想法吗?

#include <iostream>
#include <memory>


template<typename T>
class Pointered: public std::enable_shared_from_this<T>
{
public:
    using pointer=std::shared_ptr<T>;     //<-- incomplete type named error
    using weakPointer = std::weak_ptr<T>;
};


template<typename T>
using Ptr =  typename T:: pointer;

template<typename T>
using WkPtr = typename T:: weakPointer;


class Test2;

class Test:public Pointered<Test>
{
public:
    Ptr<Test2> f();
};


class Test2:public Pointered<Test2>
{
public:
    Ptr<Test> p;
    Test2(Ptr<Test> ptr):p(ptr){}
};


int main(int argc, const char * argv[])
{
    Ptr<Test> p=std::make_shared<Test>();
    Ptr<Test> p3=p;
    p->f();
    std::cout << "Refcount: " << p.use_count() << std::endl;
}


//definition differs from declaration in return type error here
Ptr<Test2> Test::f()
{
    return Ptr<Test2>(new Test2((Ptr<Test>)shared_from_this()));
}
4

1 回答 1

4

您不能转发声明嵌套类型,因为您需要封闭类型的定义,但在您的情况下,您有一个循环依赖项会阻止这一点。

首先要考虑的是循环依赖是否真的是一个好主意。在大多数情况下,循环依赖被认为是一种代码异味(表明设计存在问题)。如果你能去掉循环依赖,那么一切都会变得容易。

另一种选择是将嵌套类型的依赖关系移动到类型特征,它可以在外部和类型定义之前定义:

template <typename T>
struct pointer_traits;

template <>
struct pointer_traits<Test1> {
   typedef std::shared_ptr<Test1> ptr;
   typedef std::shared_ptr<Test1> wptr;
};

通过将依赖关系移到真实类型之外,您不再具有循环依赖关系(在语法级别,您仍然应该重新审视设计)。然后,您可以根据需要添加语法糖:

template <typename T>
using ptr = typename pointer_traits<T>::ptr;

class Test1 {
    ptr<Test2> p2;
};

如果您真的希望类型也被嵌套,您可以使用继承将它们带入范围,或者以更简单的方式添加适当的 typedef:

class Test1 {
    typedef ptr<Test1> ptr_t;
// ...

请注意,这是一个粗略的近似值,如果您选择这种方法,您可以通过添加更多语法糖来处理特征和类型的细节以使其更甜,例如,您可以为shared_ptr_traitsintrusive_ptr_traits提供两个特征单行 trait 来确定要从哪一个中提取 typedef,将 trait 的定义(每种类型)减少到单行。

于 2013-07-23T03:17:16.113 回答