模板化复制构造函数

Templated Copy-Constructor

本文关键字:构造函数 复制      更新时间:2023-10-16

>想象一下下面的例子:

#include <iostream>
#include <vector>
struct Base
{
    virtual void foo() = 0;
};
struct A : public Base
{
    void foo() override {};
};
struct B : public Base
{
    void foo() override {};
};
template <typename T>
struct C
{
    struct Element
    {
        int x, y, z;
        bool operator==(const Element& e)
        {
            if (x != e.x) return false;
            if (y != e.y) return false;
            if (z != e.z) return false;
            return true;
        }
    };
    Base* p;
    std::vector<Element> v;
    C()
    {
        p = new T();
    }
    void add(int x, int y, int z)
    {
        Element e;
        e.x = x;
        e.y = y;
        e.z = z;
        v.push_back(e);
    }
    void remove(int x, int y, int z)
    {
        Element e;
        e.x = x;
        e.y = y;
        e.z = z;
        std::vector<Element>::iterator it = std::find(v.begin(), v.end(), e);
        if (p != v.end()) v.erase(p);
    }
    void print()
    {
        for (Element e : v) std::cout << e.x << " " << e.y << " " << e.z << std::endl;
    }
};
int main()
{
    C<A> a;
    a.add(1, 2, 3);
    a.add(4, 5, 6);
    a.add(7, 8, 9);
    a.remove(4, 5, 6);
    a.print();
    return 0;
}

现在让我们在 C 中添加一个复制构造函数,以便我们可以用另一个保存另一种数据类型的 C 初始化 C(只要数据类型派生自 Base(。目标是使这成为可能:

int main()
{
    C<A> a;
    a.add(1, 2, 3);
    a.add(4, 5, 6);
    a.add(7, 8, 9);
    a.remove(4, 5, 6);
    a.print();
    C<B> b(a); // <----- This should be possible.
    return 0;
}

我试图像这样解决它:

template <typename U>
C(const C<U>& c)
{
    p = new U(*c.p);
    v = c.v;
}

但是我从Visual Studio收到以下2个错误:

错误 C2679 二进制"=":未找到采用类型为"const std::vector::Element,std::分配器<_Ty>>"的右侧操作数的运算符(或者没有可接受的转换(

错误 C2664 "A::A(A &&(":无法将参数 1 从"基数"转换为"常量 A &"

据我所知,std::vector 已经实现了一个赋值运算符,该运算符应该在运算符的右侧创建矢量的深层副本。

那么我做错了什么,我需要做些什么才能让它工作?

v = c.v;

这是两种完全不同的类型。

vstd::vector<C<T>::Element>.

c.v std::vector<C<U>::Element>.

鉴于不同的TU类型,C<T>C<U>是完全不同的类型,彼此没有关系。

C<T>::ElementC<U>::Element也是完全不同的类型。每个std::vector也是如此。

C<T>::ElementC<U>::Element 可能具有相同的类名。它们可能具有完全相同的类成员。但它们是两种独立的类型,就像彼此不同一样class Aclass B不同。问题不在于模板复制构造函数本身。问题是复制构造函数尝试将一种类型分配给彼此。

您需要做的是删除内部类Element。它不依赖于模板参数。使其成为独立的顶级类。然后,C<T>C<U> 都将有一个类成员v它是相同类型的向量,并且可以将它们分配给彼此。