1

文字列や型 T オブジェクトなどを保持できるプレースホルダー クラスとしてテンプレート クラスを作成しようとしています。以下は、私が同じために書いたコードです。

#include <iostream>
#include <string>
#include <map>

using namespace std;

//A class which act as placeholder to hold
//unknown object. Something similar as Object
//in Java
template <typename T>
class Genric
{
    public:
        map<string, T> addP; //This will be placeholder for time
        // being.
};

class A
{
    public:
        Genric t1; //Have object of Genric class so that we can
        // access the member variable in future.
        void foo()
        {
            cout<<"Calling foo"<<endl;
        }
};

int main()
{
    A a1;
    a1.foo();
}

しかし、コンパイルしようとすると、以下のエラーが発生します。

$ g++ tempClass.cxx
tempClass.cxx:21:9: error: invalid use of template-name 'Genric' without an argument list

上記の Genric クラスの目的は、将来入力できるメンバー変数の 1 つのプレースホルダー クラスとして機能することです。そのような Genric クラスを作成する方法はありますか。

4

3 に答える 3

2

次のようなものが必要ですboost::any

map<string, boost::any> anywayzz;

あらゆるオブジェクトを格納できます。Genricクラス テンプレートは必要ありません。

ブーストを使用していない場合は、any自分で実装できます。このサイトでその実装またはtype-erasureを探してください。あなたは確かにいくつかのアイデアを得るでしょう。ここから始めます:

于 2013-03-08T07:32:48.537 に答える
2

Genricテンプレート クラスとして定義していますがt1、型を指定せずに初期化しようとしています。それがあなたが得ているエラーです。例を試してください:

Genric<int> t1;

または、真のランタイムジェネリックを探している場合は、boost::anyを調べてください。

于 2013-03-08T07:32:56.140 に答える
2

プログラムがコンパイルされるまで、テンプレートは「汎用」です。その時点で、コンパイルは、処理する必要がある型を認識する必要があります。

コンパイル時に不明な(より良い:まだ知られていない)型テンプレートを含むことができるものが必要な場合、それは解決策ではありません。実際の型は実行時に認識されるため、最終的に「ハンドラー」内にラップされる、実行時ベースのポリモーフィズム (ポリモーフィック ベースからの継承) に移行する必要があります。

本質的には、型をチェックできる少なくとも仮想関数を持つベースと、その関数をall型に適した方法で実装するジェネリック派生クラスが必要です。

boost::any は実装になる可能性がありますが、特に「ランタイム型を検出できる関数」が ... にすぎないことを考えると、より簡単な方法がある可能性がありますdynamic_cast

このような解決策にたどり着くことができます

#include <memory>

class any_value
{
    template<class T>
    class wrapper; //see below

    class common_base
    {
    public:
        virtual ~common_base() {} //this makes the type polymorphic

        template<class T>
        T* has_value()
        { 
            auto* ptr = dynamic_cast<wrapper<T>*>(this); 
            return ptr? &ptr->m: nullptr;
        }
    };

    template<class T>
    class wrapper: public common_base
    {
    public:
        wrapper() :m() {}
        wrapper(const T& t) :m(t) {}

        T m;
    };

    std::unique_ptr<common_base> pb;

public:

    any_value() {}

    template<class T>
    any_value(const T& t) :pb(new wrapper<T>(t)) {}

    template<class T>
    any_value& operator=(const T& t)
    { pb = std::unique_ptr<common_base>(new wrapper<T>(t)); return *this; }

    any_value(any_value&&) =default;
    any_value& operator=(any_value&&) =default;

    //NOW THE GETTERS
    template<class T>
    T* get() const //nullptr if not holding a T*
    { return bool(pb)? pb->has_value<T>(): nullptr; }

    template<class T>
    bool get(T& t)
    { 
        T* pt = get<T>(); 
        if(pt)  t = *pt;
        return bool(pt);
    }
};

#include <iostream>
#include <string>

int main()
{
    any_value a(5), b(2.7192818), c(std::string("as a string"));
    int vi=0; double vd=0; std::string vs;

    if(!a.get(vi)) vi=0; //will go
    if(!a.get(vd)) vd=0; //will fail
    if(!a.get(vs)) vs.clear(); //will fail
    std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
    if(!b.get(vi)) vi=0; //will fail
    if(!b.get(vd)) vd=0; //will go
    if(!b.get(vs)) vs.clear(); //will fail
    std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
    if(!c.get(vi)) vi=0; //will fail
    if(!c.get(vd)) vd=0; //will fail
    if(!c.get(vs)) vs.clear(); //will go
    std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
}

Abhinavのコメントに続いて:

C++ 型システムは静的であるため、「既知」である可能性があるものを最初に逆シリアル化しない限り、一般に「不明」を逆シリアル化することはできません。

このためには、まず C++ 型 (オブジェクトではない) を認識可能な値 (type-uid のようなもの) に再設定する方法と、それらの「値」に適したラッパーを作成する「ファクトリ」が必要です。

保存するときは、そのuid を保存してから、common_base 仮想関数を介してラップされた値を保存するように要求します。ロード時には、最初に uid をロードしてから、適切なタイプの新しいラッパーを作成し(後述)、common_base 仮想関数を介して値をロードします。

適切なラッパーを作成するには、タイプ uid に関連付けられたラッパーを作成する関数に uid-s をマップするテーブルが必要です。このテーブルは、シリアル化/逆シリアル化できるようにするために必要なすべての型に対して事前に初期化する必要があります。

しかし、これはシリアライゼーション/デシリアライゼーションについて話していない元の質問から遠く離れています。

問題が「シリアル化」である場合、「型消去」は完全な解決策ではありません。「ファクトリーパターン」をもっとよく見る必要があります。そして、その議論により適した別の質問を投稿してください。

于 2013-03-08T08:43:37.687 に答える