简体   繁体   English

模板类中的通用模板指针

[英]Generic template pointer in template class

I have a template class which has a pointer to the same class (but not necessarily using the same type).我有一个模板类,它有一个指向同一个类的指针(但不一定使用相同的类型)。 Here is an example:下面是一个例子:

template<class T>
class Foo{
    Foo(){}
    Foo* a;
    template<class U>
    void bar(Foo<U>* b){a=b;}
}

When I use it in my main function, everything seems to be working until I use a different template for the argument.当我在主函数中使用它时,一切似乎都在工作,直到我为参数使用不同的模板。

int main(){
    Foo<double> f1;
    Foo<double> f2;
    f1.bar(&f1);// no Errors

    Foo<bool> f3;
    Foo<double> f4;
    f3.bar(&f4);//Error : cannot convert 'Foo<double>*' to 'Foo<bool>*'
}

Is there anyway I can define a pointer in class Foo that has a "generic" pointer to the same class in it?无论如何我可以在类Foo中定义一个指针,该指针具有指向同一类的“通用”指针?

Is there anyway I can define a pointer in class Foo that has a "generic" pointer to the same class in it?无论如何我可以在类 Foo 中定义一个指针,该指针具有指向同一类的“通用”指针?

What you have is correct.你所拥有的是正确的。 What you are expecting to see is founded on probably a misunderstanding.您期望看到的内容可能是建立在误解之上的。

Foo<bool> and Foo<double> are totally different classes. Foo<bool>Foo<double>是完全不同的类。 Type/class templates allow you to use the compiler to generate new types but they themselves are not classes.类型/类模板允许您使用编译器生成新类型,但它们本身不是类。

If you had to generate the classes manually, you would have:如果您必须手动生成类,您将拥有:

class Foo_bool{
    Foo_bool(){}
    Foo_bool* a;

    ...
};

class Foo_double{
    Foo_double(){}
    Foo_double* a;

    ...
};

With that, it's easy to see why you can't use:有了这个,很容易理解为什么你不能使用:

Foo_bool a;
Foo_double b;
a.a = &b;   // Not allowed

That is no different than using:这与使用没有什么不同:

Foo<bool> a;
Foo<double> b;
a.a = &b;   // Not allowed

The closest you can come to achieving your goal is:最接近实现目标的方法是:

  1. Create a base class for all instantiations of Foo .Foo所有实例创建一个基类。
  2. Store a pointer to the base class.存储指向基类的指针。

Simple program that demonstrates the concept:演示概念的简单程序:

class FooBase
{
   public:
      virtual ~FooBase() {}
};

template<class T>
class Foo : public FooBase {
   public:
    Foo(){}
    template<class U>
    void bar(Foo<U>* b){a=b;}

   private:
    FooBase* a; // Note the change. This is not Foo* any longer.
};

int main()
{
   Foo<bool> a;
   Foo<double> b;
   a.bar(&b);
}

Is there anyway I can define a pointer in class Foo that has a "generic" pointer to the same class in it?无论如何我可以在类 Foo 中定义一个指针,该指针具有指向同一类的“通用”指针?

That's what you already have:这就是你已经拥有的:

    Foo* a;

What you actually want, I think, is a pointer to any instantiation of Foo .我认为,您真正想要的是指向Foo任何实例化的指针。 That's not possible.那是不可能的。 The question is: why do you want that?问题是:你为什么想要那个? If you say exactly what you are trying to achieve, maybe you can get a more useful answer.如果您准确说出您要实现的目标,也许您可​​以获得更有用的答案。

One possibility might be to use a base class:一种可能性可能是使用基类:

class Base {
    // whatever common functionality you want in Foo goes here
};

template<class T>
class Foo : public Base {
    Foo(){}
    Base* a;
    template<class U>
    void bar(Foo<U>* b){a=b;}
}

Whether this will work for you is hard to say until you provide more information about what you are trying to achieve.在您提供有关您要实现的目标的更多信息之前,很难说这是否适合您。 I think we are hitting an XY problem here.我认为我们在这里遇到了XY 问题

Another possibility besides the solutions with a common base class consists of defining the type of the a data member in Foo as void * instead of Foo * .除了具有公共基类的解决方案之外,另一种可能性包括将Foo中的a数据成员的类型定义为void *而不是Foo * That way any data pointer can be assigned to it (this one would be a generic pointer ):这样任何数据指针都可以分配给它(这将是一个通用指针):

template<class T>
class Foo {
public:
    Foo(){}
    void* a;
    template<class U>
    void bar(Foo<U>* b){a=b;}

    ...
};

Then, you could define the following member template convert_ptr() to convert the pointer back to its original type:然后,您可以定义以下成员模板convert_ptr()将指针转换回其原始类型:

template<class T>
class Foo {
    ...

    template<class U>
    Foo<U>* convert_ptr() {
        return reinterpret_cast<Foo<U>*>(a);
    }
};

As an example:举个例子:

int main(){
    Foo<bool> f1;
    Foo<double> f2;

    f2.bar(&f1);
    Foo<bool> *p = f2.convert_ptr<bool>();
}

Bear in mind that not using the right template instance of convert_ptr() (eg: not casting a back to the pointer of the right type) will result in undefined behavior.请记住,并非使用权模板实例convert_ptr()如:没有铸造a回正确类型的指针)会导致不确定的行为。

How about adding an extra parameter to the template:如何向模板添加额外的参数:

template<class T, class U=T>
class Foo {
public:
    Foo() {}
    Foo<U>* a;
    void bar(Foo<U>* b) { a = b; }
};

int main(){
    Foo<bool, double> f3;
    Foo<double> f4;
    f3.bar(&f4);

    return 0;
}

If the second template parameter is not specified, it will be equal to the first one.如果未指定第二个模板参数,它将等于第一个。 And this means that your pointer "a" will point to an object of the same type as "this".这意味着您的指针“a”将指向与“this”类型相同的对象。 If the second parameter is specified and it's different from the first one, your pointer "a" will point to a different type.如果指定了第二个参数并且它与第一个参数不同,则您的指针“a”将指向不同的类型。

It's not a generic solution because you cannot change the second type once the object is created.这不是通用的解决方案,因为一旦创建了对象,就不能更改第二种类型。 But if you know from the start that但如果你从一开始就知道

Foo<bool>

needs to point to需要指向

Foo<double>

it might work.它可能会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM