模板对象可以更改其类型吗?

时间:2013-11-22 11:16:48

标签: c++ templates

我有以下课程

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>

如果我只想要一个&#34;经典&#34;赋值运算符,如果在我的课程中,我会有类似

的东西,它会工作得很好
Item<int>& operator= (const Item<double> & var) {
    this->item = var.item;
    return *this;
}

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

P.S。:我知道工会和被标记的工会,我不想用它。我的Item课程应该表现得像&#34;类似于&#34;标记的工会。

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

3 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:2)

  

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

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

答案 2 :(得分:1)

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

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

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