模板类中的通用模板指针

时间:2017-12-19 16:50:56

标签: c++ class templates pointers

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

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

当我在我的main函数中使用它时,一切似乎都在工作,直到我为参数使用不同的模板。

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中定义一个具有&#34;泛型&#34;的指针。指向同一个类的指针?

4 个答案:

答案 0 :(得分:1)

  

无论如何,我可以在类Foo中定义一个指针,它有一个&#34;泛型&#34;指向同一个类的指针?

你拥有的是正确的。你期望看到的可能是一个误解。

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. 的所有实例化创建基类
  3. 存储指向基类的指针。
  4. 演示这个概念的简单程序:

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

答案 1 :(得分:0)

  

无论如何,我可以在类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;}
}

在您提供有关您要实现的目标的更多信息之前,这对您是否有效很难说。我想我们在这里遇到XY problem

答案 2 :(得分:0)

除了具有公共基类的解决方案之外的另一种可能性包括将aFoo数据成员的类型定义为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转换回正确类型的指针)将导致未定义的行为。

答案 3 :(得分:0)

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

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”将指向与“ this”相同类型的对象。 如果指定了第二个参数,并且与第一个参数不同,则指针“ a”将指向其他类型。

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

Foo<bool>

需要指向

Foo<double>

可能有效。