1

このコードの壊れた部分を機能させるには助けが必要です。

文字列に基づいて 2 つの関数 (異なる値の型を返す) をタグ付けしてディスパッチするにはどうすればよいですか?

文字列でディスパッチする目的で全体のコードを単純化できる場合は、推奨事項を提示してください。TY.

要件:

  1. 文字列に基づくディスパッチ
  2. Rectangle オーバーロードは int を返す必要があり、Circle オーバーロードは std::string を返す必要があります
  3. Rectangle_Type から int へ、および Circle_Type から std::string へのマッピングは修正され、コンパイル時に認識されます。私の問題の一部は、std::map が実行時の構成要素であることです。std::string をコンパイル時の構成要素にタグ付けする方法がわかりません。
  4. 必要に応じて、実行時の解決は問題ありません。ただし、ディスパッチは、解決された列挙型/型に基づいて、さまざまな戻り値の型を許可する必要があります。

コード

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

struct Shape    { };
struct Rectangle_Type : public Shape { using value_type=int;         };
struct Circle_Type    : public Shape { using value_type=std::string; };

Rectangle_Type Rectangle;
Circle_Type    Circle;

static std::map<std::string,Shape*> g_mapping =
{
    { "Rectangle", &Rectangle },
    { "Circle",    &Circle    }
};

int tag_dispatch( Rectangle_Type )
{
    return 42;
}

std::string tag_dispatch( Circle_Type )
{
    return "foo";
}

int
main()
{
    std::cerr << tag_dispatch( Circle    ) << std::endl;   // OK
    std::cerr << tag_dispatch( Rectangle ) << std::endl;   // OK

#define BROKEN
#ifdef BROKEN
    std::cerr << tag_dispatch( (*g_mapping["Rectangle"]) ) << std::endl;
    std::cerr << tag_dispatch( (*g_mapping["Circle"])    ) << std::endl;
#endif
}
4

2 に答える 2

1

C++11 がこれを変更しない限り..問題は、Shape*ポインターを逆参照していることです。つまり、結果のデータ型 ( Shape&) には の有効なオーバーロードがありませんtag_dispatch

のようなことができますg_mapping["Rectangle"]->tag_dispatch()。または、よりきれいに次のように書き換えます。

std::string tag_dispatch( Shape& shape)
{
    return shape->tag_dispatch();
}

このようにShapeして、同一のインターフェースで非オブジェクトをサポートできます。tag_dispatchどちらも仮想関数として作成する必要がありますShape

于 2013-01-30T02:38:02.520 に答える
0

C++ には動的ディスパッチがありません。これはおそらくあなたが期待していることです。dynamic_cast でエミュレートできますが、これは遅く、お勧めできません。ただし、型の列挙型を返す仮想関数を使用できます。

class base
{
public:
    virtual ~base() // Don't forget the virtual destructor if you want to inherit from it!
    {}

    enum type
    {
        a, 
        b, 
    };

    virtual type get_type() const = 0;
};

class a : public base
{
public:
    virtual type get_type()
    {
        return base::type::a;
    }
};

class b : public base
{
public:
    virtual type get_type()
    {
        return base::type::b;
    }
};
于 2013-01-30T02:39:34.127 に答える