模板对象是否可以更改其类型

Can a template object change its type?

本文关键字:类型 对象 是否      更新时间:2023-10-16

我有以下类

template <typename T> class Item {
public:
    T item;
    Item () : item( T() ) {}
    Item (T arg) { this->item = arg;}
    operator T () const {
        return item;
    }
};

现在,我想编写一个赋值运算符,它还可以更改对象的类型。这可能吗?我在谷歌上搜索过,但没有任何相关内容(顺便说一句,这让我觉得我可能有点疯了)。

为了说明这一点,假设我有以下两个对象:

Item <int> intItem = 3;
Item <double> doubleItem = 3.4;

我想能够写

intItem = doubleItem;

然后,我希望intItem的类型为Item<double>

如果我只想要一个"经典"的赋值运算符,如果在我的课堂上,我有类似的东西,它会很好地工作

Item<int>& operator= (const Item<double> & var) {
    this->item = var.item;
    return *this;
}

双倍值会被四舍五入,但它会起作用。哦,intItem的类型将保持为Item<int>

附言:我知道工会和有标签的工会,我不想用这些。我的Item类的行为应该"有点像"标记的联合。

所以请给我一个答案,或者告诉我我在做梦。

不,您不能在运行时更改类型,因为模板是编译时的事情。

事实上,这就像将一个变量声明为int并尝试将其更改为float。是的,您可以将变量分配给另一个float变量,但不能更改实际变量的类型。

在此之后,我希望intItem的类型为Item。

这是不真实的,因为intItem在编译时具有Item<int>类型,而不是在运行时。

正如前两个答案所写,不,您不能在运行时更改模板的类型。

但是你可以用不同的方式来满足你的要求。取以下代码:

class Item
{
    Item()
    : data(NULL) {}
    template <typename T>
    Item(T d)
    {
        data = new Data<T>(d);
    }
    Item(const Item& other)
    : data(NULL)
    {
        if (other.data != NULL)
        {
            data = other.data->clone();
        }
    }
    ~Item()
    {
        delete data;
    }
    const Item& operator = (const Item& other)
    {
        if (this != &other)
        {
            delete data;a
            data = NULL;
            if (other.data != NULL)
            {
                data = other.data->clone();
            }
        }
        return *this;
    }
    template <typename T>
    operator T () const 
    {
        Data<T>* d = dynamic_cast<Data<T>*>(data);
        if (d != NULL)
        {
            return d->data;
        }
        else
        {
            throw std::bad_cast("");
        }
    }
private:
    struct DataBase
    {
        virtual ~DataBase() {}
        virtual DataBase* clone() = 0;
    };
    template <typanme T>
    struct Data
    {
        Data(T d)
        : data(d) {}
        virtual DataBase* clone() 
        {
            return new Data<T>(*this);
        }
        T data;
    };
    DataBase* data;
};

这基本上实现了一个Any类。例如,您可能希望查看boost::any中的现有实现。

如果你只需要支持少量的类型,你就可以实现一些类似变体的东西:

class Item
{
    enum Type
    {
        NONE,
        INT,
        DOUBLE
    };

    Item()
    : type(NONE) {}
    Item(int value)
    : type(INT)
    {
        intValue = value;
    }
    Item(double value)
    : type(DOUBLE)
    {
        doubleValue = value;
    }
    Item(const Item& other)
    {
        type = other.type;
        switch (type)
        {
            case INT:
                intValue = other.intValue;
                break;
            case DOUBLE:
                doubleValue = other.doubleValue;
                break;
        }
    }
    ~Item()
    {
        // delete any pointer types
    }
    const Item& operator = (const Item& other)
    {
        if (this != &other)
        {
            type = other.type;
            switch (type)
            {
                case INT:
                    intValue = other.intValue;
                    break;
                case DOUBLE:
                    doubleValue = other.doubleValue;
                    break;
            }
        }
        return *this;
    }
    operator int () const 
    {
        switch (type)
        {
            case NONE:
                return 0;
            case INT:
                return intValue;
                break;
            case DOUBLE:
                return static_cast<int>(doubleValue);
                break;
        }
    }
    operator double () const 
    {
        switch (type)
        {
            case NONE:
                return 0;
            case INT:
                return static_cast<double>(intValue);
                break;
            case DOUBLE:
                return doubleValue;
                break;
        }
    }
private:
    Type 
    union {
        int intValue;
        double doubleValue;
    };
};