键入别名和不完整类型 [英] Type aliases and incomplete types

查看:131
本文介绍了键入别名和不完整类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可能已经到达这里来解决应该是一个简单的问题。我在这里开始这个问题:
在编译时获取基类的类型

I'm probably over reaching here to solve what should be a simple problem. I started this question here: Getting type of base class at compile time

基本上我想让类管理它自己的指针类型。我包装一个C库,其中一些结构有参考计数嵌入在他们,其他人不。那些没有,我想使用shared_ptr。那些做,我想使用intrusive_ptr。我想避免依靠程序员智能来确保使用正确的包装器。最后,我想添加更多的依赖于这种行为的功能,但我还没有。

Basically I'm trying to make the class manage it's own pointer types. I'm wrapping a C library where some structures have reference counting embedded in them, and others do not. Those that don't, I'd like to use shared_ptr. Those that do, I'd like to use intrusive_ptr. I'd like to avoid relying on programmer intellect to ensure the use of the proper wrapper. Eventually, I'd like to add more capability that relies on this behavior, but I'm not there yet.

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

@Yakk came up with an interesting solution using template type aliases, and I've tried to implement it. Unfortunately I've got myself in a spot where I can't seem to resolve circular references to the compiler's satisfaction. I get an "incomplete type 'Test2' named in nested name specifier" error pointing to the "using pointer=" line. I also get a bizarre "definition differs from declaration in return type" for my definition of Test::f(), but I suspect that might resolve itself once I get the first error resolved.

我在这个错误类型中找到的大多数引用涉及头文件的排序,但即使在一个文件中的所有内容,我不知道如何排序的东西,使这个问题消失。

Most of the references I find on this error type involve sequencing of header files, but even with everything in one file I can't figure out how to order things to make this problem go away.

任何想法?

#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()));
}


推荐答案

,因为你需要定义封闭类型,但是在你的情况下,你有一个循环依赖来抑制这种情况。

You cannot forward declare nested types, for that you need the definition of the enclosing type, but in your case you have a cyclic dependency that inhibits this.

第一件要考虑的是循环依赖真的是个好主意。在大多数情况下,循环依赖性被认为是代码气味(设计问题的指示)。如果你可以删除循环依赖,那么一切都会变得更容易。

The first thing to consider is whether the cyclic dependency is really a good idea. In most cases cyclic dependencies are considered a code smell (an indication of problems with the design). If you can remove the cyclic dependency, then everything will become easier.

另一个不同的选择是将嵌套类型的依赖转移到类型trait,外部并且在类型的定义之前:

A different alternative is moving the dependency on the nested type to a type-trait, that can be defined externally and before the definition of the types:

template <typename T>
struct pointer_traits;

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

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

By moving the dependency outside of the real type, you no longer have the cyclic dependency (at the syntax level, you should still revisit the design). You can then add syntactic sugar as needed:

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

class Test1 {
    ptr<Test2> p2;
};

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

If you really want the types to also be nested, you can use inheritance to bring those into scope, or in a simpler way just add the appropriate typedef:

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

注意,这是一个粗略的近似,如果你选择这种方法你可以通过添加更多的语法糖,在工作细节的trait和类型以使它更加甜美,例如,你可以提供两个特征 shared_ptr_traits intrusive_ptr_traits ,并提供一个单行trait来确定你想从中拉取typedefs,减少trait的定义(每个类型)到单行。

Note, this is a rough approximation, if you opt for this approach you can work a bit on the details of the trait and the types to make it sweeter by adding more syntactic sugar, for example, you can provide two traits for shared_ptr_traits and intrusive_ptr_traits and provide a single line trait to determine from which of those you want to pull the typedefs, reducing the definition of the trait (per type) to a single line.

这篇关于键入别名和不完整类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆