模板类中的通用模板指针

Generic template pointer in template class

本文关键字:指针      更新时间:2023-10-16

我有一个模板类,该类别具有指向同一类的指针(但不一定使用相同类型)。这是一个示例:

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

当我在主要功能中使用它时,一切似乎都在起作用,直到我为参数使用其他模板。

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>*'
}

无论如何,我可以在类Foo中定义一个指针,该指针在其中具有"通用"指针?

无论如何,我可以在类FOO中定义一个指针,该指针在其中具有"通用"指针?

您拥有的是正确的。您期望看到的可能是基于误解。

Foo<bool>Foo<double>是完全不同的类。类型/类模板允许您使用编译器生成新类型,但它们本身不是类。

如果您必须手动生成课程,则会有:

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

这样,很容易看出为什么不能使用:

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

与使用:

没有什么不同
Foo<bool> a;
Foo<double> b;
a.a = &b;   // Not allowed

您可以实现目标的最接近是:

  1. Foo的所有实例创建一个基类。
  2. 存储一个指向基类的指针。

简单的程序演示了概念:

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

无论如何,我可以在类FOO中定义一个指针,该指针在其中具有"通用"指针?

这就是您已经拥有的:

    Foo* a;

我认为,您实际想要的是Foo的任何实例化的指针。那是不可能的。问题是:您为什么要想要?如果您确切地说要实现的目标,也许您可以得到一个更有用的答案。

一种可能性可能是使用基类:

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;}
}

在您提供有关要实现的目标的更多信息之前,很难说这对您有用。我认为我们在这里遇到了一个问题。

除了具有共同基类的解决方案以外的另一种可能性包括将a数据成员在Foo中定义为void *而不是Foo *。这样,任何数据指针都可以分配给它(这将是通用指针):

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

然后,您可以定义以下成员模板convert_ptr()将指针转换回原始类型:

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

作为一个例子:

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

请记住,不使用convert_ptr()的正确模板实例(例如:不施放a回到正确类型的指针)会导致不确定的行为。

如何在模板中添加额外的参数:

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;
}

如果未指定第二个模板参数,则将等于第一个模板。这意味着您的指针" a"将指出与"此"相同类型的对象。如果指定了第二个参数,并且与第一个参数不同,则您的指针" a"将指向其他类型。

这不是通用解决方案,因为创建对象后,您将无法更改第二种类型。但是,如果您从一开始就知道

Foo<bool>

需要指向

Foo<double>

它可能起作用。