3

教育目的でシンプルboost::anyなクラスを作成していますが、保存された値にアクセスする方法がわかりません。値を完全に設定できますが、「ホルダー」クラスのメンバーにアクセスしようとすると、コンパイラーは、派生元のクラスにメンバーが見つからないと文句を言うだけです。virtualテンプレートのため、メンバーを宣言できません。

関連するコードは次のとおりです。

class Element
{
    struct ValueStorageBase
    {
    };

    template <typename Datatype>
    struct ValueStorage: public ValueStorageBase
    {
        Datatype Value;

        ValueStorage(Datatype InitialValue)
        {
            Value = InitialValue;
        }
    };

    ValueStorageBase* StoredValue;

public:

    template <typename Datatype>
    Element(Datatype InitialValue)
    {
        StoredValue = new ValueStorage<Datatype>(InitialValue);
    }

    template <typename Datatype>
    Datatype Get()
    {
        return StoredValue->Value; // Error: "struct Element::ValueStorageBase" has no member named "Value."
    }
};
4

2 に答える 2

5

テンプレートに仮想関数を追加しても問題ありません。関数自体だけをテンプレートにすることはできません。テンプレート化されたクラスまたは構造体は、問題なく仮想関数を持つことができます。dynamic_cast の魔法を使用する必要があります。

class Element
{
    struct ValueStorageBase
    {
        virtual ~ValueStorageBase() {}
    };

    template <typename Datatype>
    struct ValueStorage: public ValueStorageBase
    {
        Datatype Value;

        ValueStorage(Datatype InitialValue)
        {
            Value = InitialValue;
        }
    };

    ValueStorageBase* StoredValue;

public:

    template <typename Datatype>
    Element(Datatype InitialValue)
    {
        StoredValue = new ValueStorage<Datatype>(InitialValue);
    }

    template <typename Datatype>
    Datatype Get()
    {
        if(ValueStorage<DataType>* ptr = dynamic_cast<ValueStorage<DataType>*>(StoredValue)) {
            return ptr->Value;
        else
            throw std::runtime_error("Incorrect type!"); // Error: "struct Element::ValueStorageBase" has no member named "Value."
    }
};

Get を return a に変更すると、スローする代わりにDatatype*返すことができます。NULLの以前の値のメモリも処理していませんが、それStoredValueはあなたに任せます。

于 2011-02-15T13:59:47.133 に答える
2

ValueStorage最初にキャストする必要があります。また、ValueStorageBase クラスに仮想デストラクタを追加して、ポリモーフィック クラスを作成します。それがなければ、キャストがOKかどうかを実行時にチェックできません:)。

その後、次のように記述できます。

template <typename Datatype>
    Datatype Element_cast()
    {
        //throw exception for a wrong cast
        if(typeid(*StoredValue)!=typeid(ValueStorage<Datatype>) )
               throw exception;

        //we already checked, that our type casting is OK,
        //So no need for dynamic_cast anymore
        return static_cast<ValueStorage*> (StoredValue)->value;
    }
于 2011-02-15T13:46:51.267 に答える