C++ 在类自身的指针上模板化类?

C++ 在类自身的指针上模板化类?,c++,templates,c++11,circular-dependency,C++,Templates,C++11,Circular Dependency,我想在类自己的指针上创建一个模板。我该怎么做呢 template <typename RefType, typename X> class Foo { public: RefType ptr; X val; }; typedef Foo<Foo*, int> Type1; typedef Foo<std::list<Foo>::iterator itr, int> Type2; 事先不知道x.partner的类型。i、 partner可

我想在类自己的指针上创建一个模板。我该怎么做呢

template <typename RefType, typename X>
class Foo {
 public:
  RefType ptr;
  X val;
};
typedef Foo<Foo*, int> Type1;
typedef Foo<std::list<Foo>::iterator itr, int> Type2;
事先不知道x.partner的类型。i、 partner可以是标准模板类的指针或迭代器


这是一个非常模糊的用例,我可以不使用它,但是代码看起来会更加优雅。

当然这是可能的,但是由于您的类是模板化的,当您在typedef中声明指向它的指针时,您需要选择显式类型:

using Type1 = Foo<Foo<int*, int>*, int>;
并像这样使用它:

Foo<int*, int> myFoo;
int val = 42;
myFoo.ptr = &val;
myFoo.val = 64;

Type1 myObj;
myObj.val = 1337;
myObj.ptr = &myFoo;
Foo<int> first;
first.val = 42;
first.ptr = &first; // now it refers to itself.


std::cout << first.val << std::endl;

// lets go nuts:
std::cout << first.ptr->ptr->ptr->ptr->val << std::endl;
Foo优先;
first.val=42;
first.ptr=&first;//现在它指的是它自己。

std::cout ptr->val您编写的代码无法编译的原因是,如果没有声明之外的模板参数,即使作为指针,Foo也无法运行,例如
typedef Foo Type1中的
Foo*

如果按现有方式声明该类,则可以递归地在该typedef中声明
Foo
指针,但必须在某个时刻使用非
Foo*
RefType才能使其工作。例如:

typedef Foo<Foo<Foo<int*, int>*, int>*, int> Type1;
如果由于某种原因无法更改模板,可以使用
void*
并将其重新转换为管件
Foo*

template<typename RefType, typename X>
class Foo
{
public:
    RefType ptr;
    X val;
};
typedef Foo<void*, int> Type1;

int main( )
{
    Type1 test;
    Type1* test2 = static_cast< Type1* >( test.ptr );
}
模板
福班
{
公众:
ref型ptr;
X值;
};
类型def Foo类型1;
int main()
{
1型试验;
Type1*test2=静态投影(test.ptr);
}
然而,这明显更容易出错。

使用:

模板
福班
{
公众:
ref型ptr;
X值;
};
模板
福班
{
公众:
使用TypeSelf=Foo;
TypeSelf*ptr;
X值;
};
类型def Foo类型1;

Foo
现在拥有类型为
Foo*

的成员
ptr

class Base {};

template <typename RefType, typename X>
class Foo : public Base
{
 public:
  RefType ptr;
  X val;
};
typedef Foo<Base*, int> Type1;

int main()
{
    Base* p = new Type1;
    Type1* pt = static_cast<Type1*>(p);
    pt->val = 3;
    pt->ptr = new Type1;
    (static_cast<Type1*>(pt->ptr))->val = 5;

    // delete etc.
    return 0;
}
在它的头上旋转的答案:

从Foo派生并使用它而不是typedef,而不是创建基类。这与CRTP类似

struct Type1 : public Foo<Type1 *, int> { };
struct Type2 : public Foo<std::list<Type2>::iterator, int> { };
structType1:publicfoo{};
结构类型2:公共Foo{};

您可以像使用typedef一样使用Type1和Type2。

为什么要这样做?
Foo
是一种“递归定义”。参数应该是哪种类型的
Foo
?相同的?我无法想象这种怪物类型的任何实际用例。如果
Foo
是您的模板,那么
Foo&
是参考类型。不需要作为参数传递,为什么不能直接使用
Foo*ptr在课堂上?这里的问题是,你不能只说
Foo*
;在模板化类声明之外,您必须指定您所谈论的
Foo
。这是指针指向指针的等价物,因此最终需要指定一个不指向自身的Foo。内部
Foo
与外部
Foo
@Yakk的类型不同:我不清楚这样的要求。我已编辑我的答案。未编译。在您使用
Foo
type.hmm之前,没有
Foo
。所以我只需要对指针类型做一个部分专门化,其余的就可以按原样工作了?我喜欢这个答案,因为我不必为每个引用类型写一个部分专门化。但它确实引入了虚拟函数的开销。。。
template<typename X>
class Foo
{
public:
    Foo* ptr;
    X val;
};
typedef Foo<int> Type1;
template<typename RefType, typename X>
class Foo
{
public:
    RefType ptr;
    X val;
};
typedef Foo<void*, int> Type1;

int main( )
{
    Type1 test;
    Type1* test2 = static_cast< Type1* >( test.ptr );
}
template <typename RefType, typename X>
class Foo
{
public:
    RefType ptr;
    X val;
};

template <typename X>
class Foo<void,X>
{
public:
    using TypeSelf = Foo;
    TypeSelf* ptr;
    X val;
};

typedef Foo<void,int> Type1;
class Base {};

template <typename RefType, typename X>
class Foo : public Base
{
 public:
  RefType ptr;
  X val;
};
typedef Foo<Base*, int> Type1;

int main()
{
    Base* p = new Type1;
    Type1* pt = static_cast<Type1*>(p);
    pt->val = 3;
    pt->ptr = new Type1;
    (static_cast<Type1*>(pt->ptr))->val = 5;

    // delete etc.
    return 0;
}
template<typename T>
class Base{
public:
    virtual Base<T>*& get_ptr() = 0;
    virtual T& get_val() = 0;
};

template <typename RefType, typename X>
class Foo : public Base<X>
{
 public:
  RefType ptr;
  X val;

  Base<X>*& get_ptr()
  {
    return ptr;
  }

  X& get_val()
  {
    return val;
  };

};
typedef Foo<Base<int>*, int> Type1;
typedef Base<int> BaseType;

int main()
{
    BaseType* p = new Type1;
    p->get_ptr() = new Type1;
    p->get_val() = 5;

    // delete etc.
    return 0;
}
struct Type1 : public Foo<Type1 *, int> { };
struct Type2 : public Foo<std::list<Type2>::iterator, int> { };